參考資料
本文參考資料 MDN
代碼
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
class MyPromise {
/**
* Promise 構(gòu)造函數(shù)
* @param {*} excutor 執(zhí)行器方法(同步執(zhí)行)
*/
constructor(excutor) {
this.status = PENDING; //給 promise 對象指定 status 屬性,初始值為 pending
this.data = undefined; // 給 promise 對象指定一個用于存儲結(jié)果的屬性
this.callbacks = []; // 每個元素的結(jié)構(gòu)為 {onResolved(){}, onRejected(){}}
const resolve = value => {
// 如果當前狀態(tài)不是 pending该编,直接結(jié)束
if (this.status !== PENDING) {
return;
}
// 將狀態(tài)改為 resolved
this.status = RESOLVED;
// 保存 value 數(shù)據(jù)
this.data = value;
// 如果有待執(zhí)行的 callback 函數(shù),異步執(zhí)行回調(diào) onResolved (用setTimeout執(zhí)行異步)
if (this.callbacks.length > 0) {
this.callbacks.forEach(callbacksObj => { //放到隊列中執(zhí)行所有成功的回調(diào)
setTimeout(() => {
callbacksObj.onResolved(value);
});
});
}
};
const reject = reason => {
// 如果當前狀態(tài)不是 pending,直接結(jié)束
if (this.status !== PENDING) {
return;
}
// 將狀態(tài)改為 rejected
this.status = REJECTED;
//保存 reason 數(shù)據(jù)
this.data = reason;
//如果有待執(zhí)行的 callback 函數(shù),異步執(zhí)行回調(diào)函數(shù) onRejected(用setTimeout執(zhí)行異步)
if (this.callbacks.length > 0) {
this.callbacks.forEach(callbacksObj => {
setTimeout(() => {
callbacksObj.onRejected(reason);
});
});
}
};
//立即同步執(zhí)行 excutor,如果執(zhí)行器函數(shù)拋出異常愕提,promise 對象變?yōu)?rejected 狀態(tài) (直接調(diào)用reject方法即可)
try {
excutor(resolve, reject);
} catch (error) {
reject(error);
}
}
/**
* Promise 原型對象的 then()
* @param {*} onResolved 指定成功的回調(diào)函數(shù)
* @param {*} onRejected 指定失敗的回調(diào)函數(shù)
* @return 返回一個新的 Promise 對象,返回的 Promise 的結(jié)由 onResolved/onRejected 的執(zhí)行結(jié)果決定
*/
then(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value;
// 指定默認的失敗回調(diào)(實現(xiàn)錯誤/異常傳透)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
return new MyPromise((resolve, reject) => {
/**
* 調(diào)用指定的回調(diào)函數(shù)處理,根據(jù)執(zhí)行結(jié)果皿哨,改變 return 的 promise 狀態(tài)
*
* 1. 如果回調(diào)函數(shù)拋出異常浅侨,return 的 promise 就會失敗,reason 就是 error
* 2. 如果回調(diào)函數(shù)返回的不是 promise证膨,return 的 promise 就會成功如输,value 就是返回的值
* 3. 如果回調(diào)函數(shù)返回的是一個 promise,return 的 promise 的結(jié)果就是這個 promise 的結(jié)果
*
* @param {*} callback
*/
const hander = (callback) => {
try {
const result = callback(this.data);
if (result instanceof MyPromise) { // 3.
result.then(resolve, reject); // 2.
} else {
resolve(result);
}
} catch (error) { //1.
reject(error);
}
};
switch (this.status) {
case PENDING: // 如果當前是 pending 狀態(tài),將回調(diào)函數(shù)保存起來不见,等 status 改變后在執(zhí)行
this.callbacks.push(
{
onResolved: value => hander(onResolved),
onRejected: reason => hander(onRejected)
});
break;
case RESOLVED: // 如果當前是 resolved 狀態(tài)澳化,異步執(zhí)行 onResolved,并改變 return 的 promise 狀態(tài)
setTimeout(() => {
hander(onResolved);
});
break;
case REJECTED: // 如果當前是 rejected 狀態(tài)稳吮,異步執(zhí)行 onRejected肆捕,并改變 return 的 promise 狀態(tài)
setTimeout(() => {
hander(onRejected);
});
break;
default:
break;
}
});
};
/**
* Promise 原型對象的 catch()
* @param {*} onRejected 指定失敗的回調(diào)函數(shù)
* @return 返回一個新的 Promise 對象
*/
catch(onRejected) {
return this.then(undefined, onRejected);
};
/**
* Promsie 函數(shù)對象方法(靜態(tài)方法)
* @param {*} value
* @return 返回一個指定結(jié)果的成功的 Promise 對象
*/
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
};
/**
* Promise 函數(shù)對象方法(靜態(tài)方法)
* @param {*} reason 失敗的原因
* @return 返回一個指定 reason 的失敗的 Promise 對象
*/
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
};
/**
* Promise 函數(shù)對象的 all 方法(靜態(tài)方法)
* @param {*} myPromises
* @return 返回一個 promise 只有當所有的 promise 都成功時才成功,否則只要有一個失敗則失敗
*/
static all(myPromises) {
//用來保存所有成功 value 的數(shù)組
const values = Array(myPromises.length);
//用來保存成功 promise 的數(shù)量
let resolvedCount = 0;
return new MyPromise((resolve, reject) => {
// 遍歷獲取每個Promise的結(jié)果
myPromises.forEach((p, index) => {
//p成功盖高,將成功的 value 保存到 values 中
//MyPromise.resolve(p) 說明:myPromises中的的元素有可能不是一個Promise對象慎陵,
//用 MyPromise.resolve 將其包裝成一個promise對象
MyPromise.resolve(p).then(value => {
resolvedCount++;
values[index] = value;
//如果全部成功了,將 return 的 promise 改為成功
if (resolvedCount === myPromises.length) {
resolve(values);
}
}, reason => { //只要有一個失敗了喻奥,return 的 promise 就失敗
reject(reason);
});
});
});
};
/**
* Promise 函數(shù)對象 race 方法 (類里面靜態(tài)方法)
* @param {*} myPromises
* @return 返回一個 promise席纽,其結(jié)果由第一個完成的 promise 的結(jié)果決定
*/
static race(myPromises) {
return new MyPromise((resolve, reject) => {
//返回第一個執(zhí)行完成的 promise 的結(jié)果
myPromises.forEach((p) => {
//MyPromise.resolve(p) 說明:myPromises中的的元素有可能不是一個Promise對象,
//用 MyPromise.resolve 將其包裝成一個promise對象
MyPromise.resolve(p).then(value => {
resolve(value);
}, reason => {
reject(reason);
});
});
});
};
}