UNPKG

2.67 kBJavaScriptView Raw
1/**
2 * Abortable Promise
3 *
4 * @author dondevi
5 * @create 2019-05-27
6 */
7class AbortablePromise extends Promise {
8
9 constructor (executor, abortController) {
10 super((resolve, reject) => {
11 if (!abortController) {
12 abortController = getAbortController();
13 }
14 executor(resolve, reject, abortController.signal);
15 });
16 this.abortController = abortController;
17 }
18
19 then (onFulfilled, onRejected) {
20 return new AbortablePromise((resolve, reject, signal) => {
21 const onSettled = (status, value, callback) => {
22 if ("function" === typeof callback) {
23 value = callback(value);
24 if (value instanceof AbortablePromise) {
25 Object.assign(signal, value.abortController.signal);
26 }
27 return resolve(value);
28 }
29 "resolved" === status && resolve(value);
30 "rejected" === status && reject(value);
31 }
32 super.then(
33 value => onSettled("resolved", value, onFulfilled),
34 reason => onSettled("rejected", reason, onRejected)
35 );
36 }, this.abortController);
37 }
38
39 // Equivalent to this.then(undefined, onRejected)
40 // catch (onRejected) {}
41
42 abort (reason) {
43 return new AbortablePromise((resolve, reject) => {
44 setTimeout(() => {
45 this.abortController.abort(reason);
46 this.then(resolve, reject);
47 });
48 }, this.abortController);
49 }
50
51};
52
53AbortablePromise.all = function (promises) {
54 return new AbortablePromise((resolve, reject, signal) => {
55 signal.onabort = reason => {
56 promises.forEach((promise) => {
57 if (promise instanceof AbortablePromise) {
58 promise.abort(reason).catch(reject);
59 }
60 });
61 reject(reason);
62 }
63 Promise.all(promises).then(resolve, reject);
64 });
65}
66
67AbortablePromise.race = function (promises) {
68 return new AbortablePromise((resolve, reject, signal) => {
69 signal.onabort = reason => {
70 promises.forEach((promise) => {
71 if (promise instanceof AbortablePromise) {
72 promise.abort(reason).catch(reject);
73 }
74 });
75 reject(reason);
76 }
77 Promise.race(promises).then(resolve, reject);
78 });
79}
80
81/**
82 * Custom AbortController
83 *
84 * @return {Object} abortController
85 */
86function getAbortController () {
87 const abortSignal = {
88 aborted: false,
89 onabort: null
90 };
91 const abort = reason => {
92 if (abortSignal.aborted) { return; }
93 const { onabort } = abortSignal;
94 "function" === typeof onabort && onabort(reason);
95 abortSignal.aborted = true;
96 };
97 const abortController = {
98 signal: abortSignal,
99 abort: abort
100 };
101 return abortController;
102}
103
104module.exports = AbortablePromise;