p_cancelable.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. 'use strict';
  2. // Try getting the real promise object from the context, if available. Someone
  3. // could have overridden it in a test.
  4. const Promise = global[Symbol.for('jest-native-promise')] || global.Promise;
  5. class CancelError extends Error {
  6. constructor() {
  7. super('Promise was canceled');
  8. this.name = 'CancelError';
  9. }
  10. }
  11. class PCancelable {
  12. static fn(fn) {
  13. return function () {
  14. const args = [].slice.apply(arguments);
  15. return new PCancelable((onCancel, resolve, reject) => {
  16. args.unshift(onCancel);
  17. fn.apply(null, args).then(resolve, reject);
  18. });
  19. };
  20. }
  21. constructor(executor) {
  22. this._pending = true;
  23. this._canceled = false;
  24. this._promise = new Promise((resolve, reject) => {
  25. this._reject = reject;
  26. return executor(fn => {
  27. this._cancel = fn;
  28. }, val => {
  29. this._pending = false;
  30. resolve(val);
  31. }, err => {
  32. this._pending = false;
  33. reject(err);
  34. });
  35. });
  36. }
  37. then() {
  38. return this._promise.then.apply(this._promise, arguments);
  39. }
  40. catch() {
  41. return this._promise.catch.apply(this._promise, arguments);
  42. }
  43. cancel() {
  44. if (!this._pending || this._canceled) {
  45. return;
  46. }
  47. if (typeof this._cancel === 'function') {
  48. try {
  49. this._cancel();
  50. } catch (err) {
  51. this._reject(err);
  52. }
  53. }
  54. this._canceled = true;
  55. this._reject(new CancelError());
  56. }
  57. get canceled() {
  58. return this._canceled;
  59. }
  60. }
  61. Object.setPrototypeOf(PCancelable.prototype, Promise.prototype);
  62. module.exports = PCancelable;
  63. module.exports.CancelError = CancelError;