🔗
Promise/A+
規範:
- 三種狀態
pending| fulfilled(resolved) | rejected
- 當處於
pending
狀態的時候,可以轉移到fulfilled(resolved)
或者rejected
狀態 - 當處於
fulfilled(resolved)
狀態或者rejected
狀態的時候,就不可變。
必須有一個 then
異步執行方法,then
接受兩個參數且必須返回一個 promise:
// onFulfilled 用來接收promise成功的值
// onRejected 用來接收promise失敗的原因
promise1 = promise.then(onFulfilled, onRejected);
1. Promise
的流程圖分析
回顧下 Promise 的用法:
var promise = new Promise((resolve,reject) => {
if (操作成功) {
resolve(value)
} else {
reject(error)
}
})
promise.then(function (value) {
// success
},function (value) {
// failure
})
2. 面試夠用版
function myPromise(constructor){
let self=this;
self.status="pending" //定義狀態改變前的初始狀態
self.value=undefined;//定義狀態爲resolved的時候的狀態
self.reason=undefined;//定義狀態爲rejected的時候的狀態
function resolve(value){
//兩個==="pending",保證了狀態的改變是不可逆的
if(self.status==="pending"){
self.value=value;
self.status="resolved";
}
}
function reject(reason){
//兩個==="pending",保證了狀態的改變是不可逆的
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
}
}
//捕獲構造異常
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
同時,需要在 myPromise
的原型上定義鏈式調用的 then
方法:
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
測試一下:
var p=new myPromise(function(resolve,reject){resolve(1)});
p.then(function(x){console.log(x)}); //輸出1
3. 大廠專供版
直接貼出來:
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function Promise(excutor) {
let that = this; // 緩存當前promise實例對象
that.status = PENDING; // 初始狀態
that.value = undefined; // fulfilled狀態時 返回的信息
that.reason = undefined; // rejected狀態時 拒絕的原因
that.onFulfilledCallbacks = []; // 存儲fulfilled狀態對應的onFulfilled函數
that.onRejectedCallbacks = []; // 存儲rejected狀態對應的onRejected函數
function resolve(value) { // value成功態時接收的終值
if(value instanceof Promise) {
return value.then(resolve, reject);
}
// 實踐中要確保 onFulfilled 和 onRejected 方法異步執行,且應該在 then 方法被調用的那一輪事件循環之後的新執行棧中執行。
setTimeout(() => {
// 調用resolve 回調對應onFulfilled函數
if (that.status === PENDING) {
// 只能由pending狀態 => fulfilled狀態 (避免調用多次resolve reject)
that.status = FULFILLED;
that.value = value;
that.onFulfilledCallbacks.forEach(cb => cb(that.value));
}
});
}
function reject(reason) { // reason失敗態時接收的拒因
setTimeout(() => {
// 調用reject 回調對應onRejected函數
if (that.status === PENDING) {
// 只能由pending狀態 => rejected狀態 (避免調用多次resolve reject)
that.status = REJECTED;
that.reason = reason;
that.onRejectedCallbacks.forEach(cb => cb(that.reason));
}
});
}
// 捕獲在excutor執行器中拋出的異常
// new Promise((resolve, reject) => {
// throw new Error('error in excutor')
// })
try {
excutor(resolve, reject);
} catch (e) {
reject(e);
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
const that = this;
let newPromise;
// 處理參數默認值 保證參數後續能夠繼續執行
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function" ? onRejected : reason => {
throw reason;
};
if (that.status === FULFILLED) { // 成功態
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try{
let x = onFulfilled(that.value);
resolvePromise(newPromise, x, resolve, reject); // 新的promise resolve 上一個onFulfilled的返回值
} catch(e) {
reject(e); // 捕獲前面onFulfilled中拋出的異常 then(onFulfilled, onRejected);
}
});
})
}
if (that.status === REJECTED) { // 失敗態
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(that.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
if (that.status === PENDING) { // 等待態
// 當異步調用resolve/rejected時 將onFulfilled/onRejected收集暫存到集合中
return newPromise = new Promise((resolve, reject) => {
that.onFulfilledCallbacks.push((value) => {
try {
let x = onFulfilled(value);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
that.onRejectedCallbacks.push((reason) => {
try {
let x = onRejected(reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
};