CancelToken.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 'use strict';
  2. var Cancel = require('./Cancel');
  3. /**
  4. * A `CancelToken` is an object that can be used to request cancellation of an operation.
  5. *
  6. * @class
  7. * @param {Function} executor The executor function.
  8. */
  9. function CancelToken(executor) {
  10. if (typeof executor !== 'function') {
  11. throw new TypeError('executor must be a function.');
  12. }
  13. var resolvePromise;
  14. this.promise = new Promise(function promiseExecutor(resolve) {
  15. resolvePromise = resolve;
  16. });
  17. var token = this;
  18. // eslint-disable-next-line func-names
  19. this.promise.then(function(cancel) {
  20. if (!token._listeners) return;
  21. var i;
  22. var l = token._listeners.length;
  23. for (i = 0; i < l; i++) {
  24. token._listeners[i](cancel);
  25. }
  26. token._listeners = null;
  27. });
  28. // eslint-disable-next-line func-names
  29. this.promise.then = function(onfulfilled) {
  30. var _resolve;
  31. // eslint-disable-next-line func-names
  32. var promise = new Promise(function(resolve) {
  33. token.subscribe(resolve);
  34. _resolve = resolve;
  35. }).then(onfulfilled);
  36. promise.cancel = function reject() {
  37. token.unsubscribe(_resolve);
  38. };
  39. return promise;
  40. };
  41. executor(function cancel(message) {
  42. if (token.reason) {
  43. // Cancellation has already been requested
  44. return;
  45. }
  46. token.reason = new Cancel(message);
  47. resolvePromise(token.reason);
  48. });
  49. }
  50. /**
  51. * Throws a `Cancel` if cancellation has been requested.
  52. */
  53. CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  54. if (this.reason) {
  55. throw this.reason;
  56. }
  57. };
  58. /**
  59. * Subscribe to the cancel signal
  60. */
  61. CancelToken.prototype.subscribe = function subscribe(listener) {
  62. if (this.reason) {
  63. listener(this.reason);
  64. return;
  65. }
  66. if (this._listeners) {
  67. this._listeners.push(listener);
  68. } else {
  69. this._listeners = [listener];
  70. }
  71. };
  72. /**
  73. * Unsubscribe from the cancel signal
  74. */
  75. CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
  76. if (!this._listeners) {
  77. return;
  78. }
  79. var index = this._listeners.indexOf(listener);
  80. if (index !== -1) {
  81. this._listeners.splice(index, 1);
  82. }
  83. };
  84. /**
  85. * Returns an object that contains a new `CancelToken` and a function that, when called,
  86. * cancels the `CancelToken`.
  87. */
  88. CancelToken.source = function source() {
  89. var cancel;
  90. var token = new CancelToken(function executor(c) {
  91. cancel = c;
  92. });
  93. return {
  94. token: token,
  95. cancel: cancel
  96. };
  97. };
  98. module.exports = CancelToken;