lib/amd/src/pending.js

  1. // This file is part of Moodle - http://moodle.org/
  2. //
  3. // Moodle is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // Moodle is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * A helper used to inform Behat that an operation is in progress and that Behat must wait for it to complete.
  17. *
  18. * @module core/pending
  19. * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. * @since 3.6
  22. */
  23. /**
  24. * A helper used to register any long-running operations that are in-progress and that Behat must wait for it to complete.
  25. *
  26. * This is useful in cases where the user interface may be updated and take some time to change - for example where
  27. * applying a transition.
  28. *
  29. * This data is used by Behat, but may also be consumed by other location too.
  30. *
  31. * By informing Behat that an action is about to happen, and then that it is complete, allows
  32. * Behat to wait for that completion and avoid random failures in automated testing.
  33. *
  34. * Note: It is recommended that a descriptive key be used to aid in debugging where possible, but this is optional.
  35. */
  36. export default class {
  37. /**
  38. * Create a new Pending Promise statically.
  39. *
  40. * @param {String} pendingKey An identifier to help in debugging
  41. * @return {Promise} A Native Promise
  42. * @deprecated since Moodle 4.2
  43. */
  44. static request(pendingKey) {
  45. window.console.error(
  46. `The core/pending::request method has been deprecated. ` +
  47. `Please use one of the alternative calls to core/pending, for example "new Pending('${pendingKey}')". ` +
  48. `Called with ${pendingKey}`
  49. );
  50. return new this(pendingKey);
  51. }
  52. /**
  53. * Request a new pendingPromise for later resolution.
  54. *
  55. * When the action you are performing is complete, simply call resolve on the returned Promise.
  56. *
  57. * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging
  58. * @return {Promise} A Native Promise
  59. * @example
  60. * import Pending from 'core/pending';
  61. * import {getString} from 'core/str';
  62. *
  63. * const stringPromise = new Pending('mod_myexample/setup');
  64. * const myString = getString('ok')
  65. * .then(okay => {
  66. * window.console.log(okay);
  67. * })
  68. * .then(okay => stringPromise.resolve(okay));
  69. */
  70. constructor(pendingKey = 'pendingPromise') {
  71. let resolver;
  72. let rejector;
  73. const pendingPromise = this.constructor.Promise((resolve, reject) => {
  74. resolver = resolve;
  75. rejector = reject;
  76. }, pendingKey);
  77. pendingPromise.resolve = resolver;
  78. pendingPromise.reject = rejector;
  79. return pendingPromise;
  80. }
  81. /**
  82. * Create a new Pending Promise with the same interface as a native Promise.
  83. *
  84. * @param {Callable} fn A callable which takes the resolve and reject arguments as in a Native Promise constructor.
  85. * @param {String} [pendingKey='pendingPromise'] An identifier to help in debugging
  86. * @returns {Promise}
  87. * @since Moodle 4.2
  88. * @example
  89. * // Use the Pending class in the same way that you would a Native Promise.
  90. * import Pending from 'core/pending';
  91. * import {getString} from 'core/str';
  92. *
  93. * export const init => {
  94. * Pending.Promise((resolve, reject) => {
  95. * getString('ok')
  96. * .then(okay => {
  97. * window.console.log(okay);
  98. * return okay;
  99. * })
  100. * .then(resolve)
  101. * .catch(reject);
  102. * }, 'mod_myexample/setup:init');
  103. * };
  104. */
  105. static Promise(fn, pendingKey = 'pendingPromise') {
  106. const resolver = new Promise((resolve, reject) => {
  107. M.util.js_pending(pendingKey);
  108. fn(resolve, reject);
  109. });
  110. resolver.then(() => {
  111. M.util.js_complete(pendingKey);
  112. return;
  113. }).catch();
  114. return resolver;
  115. }
  116. }