You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 1.3KB

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