Retries.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*************************************************************
  2. *
  3. * Copyright (c) 2017-2022 The MathJax Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /**
  18. * @fileoverview Implements methods for handling asynchronous actions
  19. *
  20. * @author dpvc@mathjax.org (Davide Cervone)
  21. */
  22. /*****************************************************************/
  23. /*
  24. * The legacy MathJax object (FIXME: remove this after all v2 code is gone)
  25. */
  26. declare var MathJax: {Callback: {After: Function}};
  27. /*****************************************************************/
  28. /**
  29. * Allow us to pass a promise as part of an Error object
  30. */
  31. export interface RetryError extends Error {
  32. retry: Promise<any>;
  33. }
  34. /*****************************************************************/
  35. /**
  36. * A wrapper for actions that may be asynchronous. This will
  37. * rerun the action after the asychronous action completes.
  38. * Usually, this is for dynamic loading of files. Legacy
  39. * MathJax does that a lot, so we still need it for now, but
  40. * may be able to go without it in the future.
  41. *
  42. * Example:
  43. *
  44. * HandleRetriesFor(() => {
  45. *
  46. * html.findMath()
  47. * .compile()
  48. * .getMetrics()
  49. * .typeset()
  50. * .updateDocument();
  51. *
  52. * }).catch(err => {
  53. * console.log(err.message);
  54. * });
  55. *
  56. * @param {Function} code The code to run that might cause retries
  57. * @return {Promise} A promise that is satisfied when the code
  58. * runs completely, and fails if the code
  59. * generates an error (that is not a retry).
  60. */
  61. export function handleRetriesFor(code: Function): Promise<any> {
  62. return new Promise(function run(ok: Function, fail: Function) {
  63. try {
  64. ok(code());
  65. } catch (err) {
  66. if (err.retry && err.retry instanceof Promise) {
  67. err.retry.then(() => run(ok, fail))
  68. .catch((perr: Error) => fail(perr));
  69. } else if (err.restart && err.restart.isCallback) {
  70. // FIXME: Remove this branch when all legacy code is gone
  71. MathJax.Callback.After(() => run(ok, fail), err.restart);
  72. } else {
  73. fail(err);
  74. }
  75. }
  76. });
  77. }
  78. /*****************************************************************/
  79. /**
  80. * Tells HandleRetriesFor() to wait for this promise to be fulfilled
  81. * before rerunning the code. Causes an error to be thrown, so
  82. * calling this terminates the code at that point.
  83. *
  84. * @param {Promise} promise The promise that must be satisfied before
  85. * actions will continue
  86. */
  87. export function retryAfter(promise: Promise<any>) {
  88. let err = new Error('MathJax retry') as RetryError;
  89. err.retry = promise;
  90. throw err;
  91. }