Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
PromiseA+规范中文版
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| class MyPromise { constructor(executor) { this.status = "pending"; this.value = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = [];
this.useMicroTask = typeof queueMicrotask === 'function' || typeof process?.nextTick === 'function';
const resolve = (value) => { if (value instanceof MyPromise) { return value.then(resolve, reject); } this.asyncTask(() => { if (this.status === 'pending') { this.value = value; this.status = 'resolved'; this.onResolvedCallbacks.forEach(fn => fn(value)); } }); };
const reject = (reason) => { this.asyncTask(() => { if (this.status === 'pending') { this.value = reason; this.status = 'rejected'; this.onRejectedCallbacks.forEach(fn => fn(reason)); } }); };
try { executor(resolve, reject); } catch (e) { reject(e); } }
asyncTask(fn) { if (this.useMicroTask) { if (typeof queueMicrotask === 'function') { queueMicrotask(fn); } else if (typeof process?.nextTick === 'function') { process.nextTick(fn); } } else { setTimeout(fn, 0); } }
then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
const promise2 = new MyPromise((resolve, reject) => { const handleFulfilled = () => { this.asyncTask(() => { try { const x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); };
const handleRejected = () => { this.asyncTask(() => { try { const x = onRejected(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); };
if (this.status === 'resolved') { handleFulfilled(); } else if (this.status === 'rejected') { handleRejected(); } else { this.onResolvedCallbacks.push(handleFulfilled); this.onRejectedCallbacks.push(handleRejected); } });
return promise2; }
catch(onRejected) { return this.then(null, onRejected); }
static resolve(value) { return value instanceof MyPromise ? value : new MyPromise(resolve => resolve(value)); } }
function resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { reject(new TypeError('循环引用')); return; }
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call( x, y => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, r => { if (called) return; called = true; reject(r); } ); } else { resolve(x); } } catch (e) { if (called) return; called = true; reject(e); } } else { resolve(x); } }
|
测试
1 2 3 4 5 6 7 8 9 10
| MyPromise.deferred = function () { const obj = {};
obj.promise = new MyPromise(function (resolve, reject) { obj.resolve = resolve; obj.reject = reject; });
return obj; };
|
保存MyPromise代码和上面代码创建 test.js 文件,并运行以下命令测试
1
| npx promises-aplus-tests test.js
|
可以看到MyPromise通过 872个测试 符合 Promise/A+ 规范了!