問題
function Promise(xxx) {
xxx
return xxx
}
var promise = new Promise(function(x, y){
setTimeout(() => {
x(101)
}, 3000)
})
promise.then((z) => {
console.log(z) // 101
})
解決思路
- 從上面使用自己實(shí)現(xiàn)的
Promise
時(shí)晶衷,可以看到傳入的參數(shù)是一個(gè)函數(shù),那么確定Promise
的參數(shù)類型是Function
抄邀,同時(shí)它返回的內(nèi)容里還有一個(gè)then
方法耘眨,它也接受一個(gè)函數(shù)作為參數(shù)昼榛,根據(jù)對(duì)Promise
的了解境肾,它應(yīng)接受兩個(gè)函數(shù):
function Promise(fn) {
...
return {
then: function(successFn, errorFn) {
return undefiend; //如果不寫默認(rèn)return undefined,這里我們只做一次then胆屿,如果要用then鏈奥喻,可能需要遞歸調(diào)用
}
}
}
- 同時(shí)我們需要去執(zhí)行傳進(jìn)來(lái)的這個(gè)函數(shù),它實(shí)際上有兩個(gè)函數(shù)作為參數(shù)非迹,則必然:
function Promise(fn) {
fn.call(undefined, successNotify, errorNotify); // fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
- fn接受的兩個(gè)函數(shù)需要單獨(dú)定義:
function Promise(fn) {
function successNotify() {}
function errorNotify() {}
fn.call(undefined, successNotify, errorNotify); // fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
- 為了讓fn的處理函數(shù)能夠正確反映Promise的狀態(tài)环鲤,需要添加一個(gè)狀態(tài)變量:
function Promise(fn) {
let status = 'pending';
function successNotify() {
status = 'resolved';
}
function errorNotify() {
status = 'rejected';
}
fn.call(undefined, successNotify, errorNotify); // fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
- 接下來(lái)我們要處理then傳進(jìn)來(lái)的函數(shù),如果成功你那個(gè)解決了憎兽,就要處理then傳進(jìn)來(lái)的成功函數(shù)冷离,否則要處理失敗函數(shù),因此用兩個(gè)單獨(dú)的隊(duì)列放傳進(jìn)來(lái)的函數(shù):
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
}
function errorNotify() {
status = 'rejected';
}
fn.call(undefined, successNotify, errorNotify); //fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不寫默認(rèn)return undefined纯命,這里我們只做一次then西剥,如果要用then鏈,可能需要遞歸調(diào)用
}
}
}
- 只有在處理好之后才會(huì)處理then里面?zhèn)鬟f的內(nèi)容亿汞,新增一個(gè)對(duì)then的處理函數(shù):
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
handleThen.apply(undefined, arguments);
}
function errorNotify() {
status = 'rejected';
handleThen.apply(undefined, arguments);
}
function handleThen() {
if (status === 'resolved') {
for (let i = 0; i < successArray.length; i++) {
successArray[i].apply(undefined, arguments);
}
} else if (status === 'rejected') {
for (let i = 0; i < errorArray.length; i++) {
errorArray[i].apply(undefined, arguments);
}
}
}
fn.call(undefined, successNotify, errorNotify); //fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不寫默認(rèn)return undefined瞭空,這里我們簡(jiǎn)化,只做一次then,如果要用then鏈咆畏,可能需要遞歸調(diào)用
}
}
}
- 為了確蹦衔妫回調(diào)是異步執(zhí)行的,用setTimeout裹一層:
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
handleThen.apply(undefined, arguments);
}
function errorNotify() {
status = 'rejected';
handleThen.apply(undefined, arguments);
}
function handleThen() {
setTimeout(() => {
if (status === 'resolved') {
for (let i = 0; i < successArray.length; i++) {
successArray[i].apply(undefined, arguments);
}
} else if (status === 'rejected') {
for (let i = 0; i < errorArray.length; i++) {
errorArray[i].apply(undefined, arguments);
}
}
});
}
fn.call(undefined, successNotify, errorNotify); //fn接受兩個(gè)函數(shù)作為參數(shù)
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不寫默認(rèn)return undefined旧找,這里我們簡(jiǎn)化溺健,只做一次then,如果要用then鏈钦讳,可能需要遞歸調(diào)用
}
}
}