這裏超級安利你們去看《深刻淺出nodejs》4.3.2 章節,別問我爲啥總是安利這個,問就真的好看啊!!javascript
promise的規範有一大堆,可是es6採用了Promise A+ 規範html
相關文檔 Promise A+規範的友情解釋連接 規範說明英文版java
相信你們看完上面給的那個鏈接已經對整個promise的執行過程都有個瞭解了。 這裏總結下node
如下爲菜狗子根據規範約定實(chao)現(xi),有錯歡迎指出。git
大佬們封裝的promise實現測試工具,有實現完成的,能夠用這個測試下是否符合標準。es6
大佬們封裝好的例子想要看更多的,能夠看這裏。菜狗子的實現參考其中belofte.js爲方便理解(就是懶)砍掉了許多類型判斷。github
註釋寫的比我多,講的比我細緻的一篇文章promise
const PENDING = "Pending";
const FULFILLED = "Fulfilled";
const REJECTED = "Rejected";
const root = typeof window === "undefined" ? global : window;
const isFunction = data => typeof data === "function";
const isMyPromise = fn => fn instanceof MyPromise;
const isObject = data =>
data && (typeof data === "object" || typeof data === "function");
// 由於promise是微任務,咱們儘量的去模擬
const nextTick = (function() {
if (typeof root.process === "object" && isFunction(root.process.nextTick)) {
// node環境
return function(fn) {
// process.nextTick 是微任務
root.process.nextTick(fn);
};
} else {
// 瀏覽器環境
return function(fn) {
// setTimeout 是宏任務
root.setTimeout(fn, 0);
};
}
})();
// 將promise由中間態到終態
const promiseResolutionProcedure = function(promise, result, async = true) {
if (promise === result) {
/** * 由於promise 若是收到的value是一個promise會等待他的結果。 * 因此若是接受到的value是自己就遞歸了。 * * @see https://promisesaplus.com/ 2.3.1 條規定 */
promise._reject(new TypeError("Chaining cycle detected for promise"));
return;
}
// 若是接收到的是個promise
if (isMyPromise(result)) {
switch (result._state) {
case FULFILLED: {
nextTick(function() {
promise._resolve(result._value);
});
break;
}
case REJECTED: {
nextTick(function() {
promise._reject(result._reason);
});
break;
}
case PENDING: {
const _resolve = result._resolve;
const _reject = result._reject;
result._resolve = function(value) {
_resolve.call(result, value);
promise._resolve(value);
}.bind(result);
result._reject = function(reason) {
_reject.call(result, reason);
promise._reject(reason);
}.bind(result);
break;
}
}
return;
}
// 若是接受到的是個thenable 對象
if (isObject(result) && isFunction(result.then)) {
/** * 屢次調用只有第一次有效 * * @see https://promisesaplus.com/ 2.3.3.3.3 條規定 */
let flag = false;
const _resolve = function(value) {
if (flag) {
return;
}
flag = true;
promiseResolutionProcedure(promise, value);
};
const _reject = function(reason) {
if (flag) {
return;
}
flag = true;
promise._reject(reason);
};
const thenTemp = function() {
try {
result.then(_resolve, _reject);
} catch (error) {
_reject(error);
}
};
if (async) {
nextTick(thenTemp);
} else {
thenTemp();
}
return;
}
promise._resolve(result);
return;
};
class MyPromise {
constructor(resolver) {
if (!isFunction(resolver)) {
throw new TypeError("Promise resolver undefined is not a function");
}
/** @type { PENDING | FULFILLED | REJECTED} */
this._state = PENDING;
this._value = undefined;
this._reason = undefined;
this._isPromise = true;
/** * 由於同一個promise能夠被then 屢次。 * 這裏的屢次不是指鏈式調用!!!! * 這裏理解了很久TAT */
this._resolveFnQueues = [];
this._rejectFnQueuse = [];
promiseResolutionProcedure(this, { then: resolver }, false);
}
_resolve(value) {
if (this._state !== PENDING) {
return;
}
this._state = FULFILLED;
this._value = value;
if (this._resolveFnQueues.length) {
nextTick(() => {
this._resolveFnQueues.forEach(cb => cb(value));
this._resolveFnQueues.length = 0;
this._rejectFnQueuse.length = 0;
});
}
}
_reject(reason) {
if (this._state !== PENDING) {
return;
}
this._state = FULFILLED;
this._reason = reason;
if (this._rejectFnQueuse.length) {
nextTick(() => {
this._rejectFnQueuse.forEach(cb => cb(reason));
this._resolveFnQueues.length = 0;
this._rejectFnQueuse.length = 0;
});
}
}
// then註冊一個監聽,在這個promise onFulfilled 或者 onRejected
then(onFulfilled, onRejected) {
onFulfilled = isFunction(onFulfilled) ? onFulfilled : MyPromise.resolve;
onRejected = isFunction(onRejected) ? onRejected : MyPromise.reject;
const chainPromise = new MyPromise(function() {});
const nextOnFulfilled = function(value) {
let result;
try {
result = onFulfilled(value);
promiseResolutionProcedure(chainPromise, result);
} catch (error) {
chainPromise._reject(error);
}
};
const nextOnRejected = function(reason) {
let result;
try {
result = onRejected(reason);
promiseResolutionProcedure(chainPromise, result);
} catch (error) {
chainPromise._reject(error);
}
};
switch (this._state) {
case FULFILLED: {
nextTick(() => {
nextOnFulfilled(this._value);
});
break;
}
case REJECTED: {
nextTick(() => {
nextOnRejected(this._reason);
});
break;
}
case PENDING: {
this._resolveFnQueues.push(nextOnFulfilled);
this._rejectFnQueuse.push(nextOnRejected);
}
}
return chainPromise;
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
toString() {
switch (this._state) {
case PENDING:
return "Promise { <pending> }";
case FULFILLED:
return "Promise { " + this._value + " }";
case REJECTED:
return "Promise { <rejected> " + this._reason + " }";
}
}
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject() {
return new MyPromise((resolve, reject) => reject(value));
}
}
複製代碼
async 本質就是將 Generator 函數和自動執行器,包裝在一個函數裏瀏覽器
阮一峯大大的文章講的炒雞清楚了。這裏的內容也來自於那篇文章,本人也就溫習實現一下.async
// async 的寫法
async function fn(args){
// ...
}
// 等同於
function fn(args){
return spawn(function*() {
// ...
});
}
//spawn 的實現方式
function spawn(genF) {
return new Promise(function(resolve, reject) {
var gen = genF();
step(function() { return gen.next(undefined); });
function step(nextF) {
try {
var next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
});
}
複製代碼