前言
如果想實作一個Promise 需要從以下幾個方面考慮
- 符合 promise A+規範
- Promise類的設計
- 狀态設計(pending/fulfilled/reject)
- 如何實作 resolve
- 如何實作 reject
- 如何實作 then
什麼是Promise A+ 規範
promisesaplus
- “promise” is an object or function with a
method whose behavior conforms to this specification.then
- “thenable” is an object or function that defines a
method.then
- “value” is any legal JavaScript value (including
, a thenable, or a promise).undefined
- “exception” is a value that is thrown using the
statement.throw
- “reason” is a value that indicates why a promise was rejected.
- A promise must be in one of three states: pending, fulfilled, or rejected.
promise類的設計
我們在使用 Promise的時候,都是通過 new 關鍵字調用, 是以借助 ES6 class 實作 Promise的聲明
class DDFPromise {
constructor(executor) {
executor(executor);
}
複制代碼
複制
實作Promise 三種狀态
我們在使用Promise時,注意到,Promise有三種狀态 fulfill/reject/pending
- new Promise(()=> {}) 此時的狀态為pending
- new Promise(()=> {}).then() 此時的狀态為fulfill
- new Promise(()=> {}).catch() 此時的狀态為reject
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
constructor(executor) {
this.status = PENDING_STATUS;
executor(executor);
}
}
new DDFPromise(() => {
console.log("代碼執行");
});
複制代碼
複制
如何實作 resolve
實作resolve 需要關注兩個點
- 狀态
- 傳回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = null;
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILL_STATUS;
console.log("resolve被執行", value);
** **this.value = value
}
};
executor(resolve);
}
}
new DDFPromise((resolve) => resolve("resolve傳入的參數"))
複制代碼
複制
如何實作 reject
實作resolve 需要關注兩個點
- 狀态
- 傳回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = null;
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILL_STATUS;
console.log("resolve被執行", value);
this.value = value
}
};
const reject = (reason) => {
if (this.status === PENDING_STATUS) {
this.status = REJECT_STATUS;
this.reason = reason;
}
};
executor(resolve, reject);
}
}
new DDFPromise((resolve, reject) => {
resolve("resolve傳入的參數");
reject("reject傳入的參數");
})
複制代碼
複制
如何實作 then
實作then 需要關注 以下幾點
- then方法的兩個入參
- then方法的兩個入參 如何與constructor中定義的resolve/reject做關聯
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILL_STATUS;
this.value = value;
this.onfulfilled(this.value);
}
};
const reject = (reason) => {
if (this.status === PENDING_STATUS) {
this.status = REJECT_STATUS;
this.reason = reason;
this.onrejected(this.reason);
}
};
executor(resolve, reject);
}
then(onfulfilled, onrejected) {
this.onfulfilled = onfulfilled;
this.onrejected = onrejected;
}
}
const ddfPro = new DDFPromise((resolve, reject) => {
resolve("resolve傳入的參數");
// reject("reject傳入的參數");
});
ddfPro.then(
(res) => {
console.log("fulfilled", res);
},
(err) => {
console.log("reject", err);
}
);
複制代碼
複制
上邊代碼執行時報錯 this.onfulfilled is not a function,報錯的原因:new Prose(()=>{}) 入參的代碼會立刻執行,而執行時this.onrejected,還沒有聲明,其實我們可以借助 Event Loop 解決此問題
解決then方法聲明 調用時報錯
queueMicrotask | setTimeout
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
constructor(executor) {
this.status = PENDING_STATUS;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.status === PENDING_STATUS) {
this.status = FULFILL_STATUS;
queueMicrotask(() => {
this.value = value;
this.onfulfilled(this.value);
});
}
};
const reject = (reason) => {
if (this.status === PENDING_STATUS) {
this.status = REJECT_STATUS;
queueMicrotask(() => {
this.reason = reason;
this.onrejected(this.reason);
});
}
};
executor(resolve, reject);
}
then(onfulfilled, onrejected) {
this.onfulfilled = onfulfilled;
this.onrejected = onrejected;
}
}
const ddfPro = new DDFPromise((resolve, reject) => {
// resolve("resolve傳入的參數");
// reject("reject傳入的參數");
});
ddfPro.then(
(res) => {
console.log("fulfilled", res);
},
(err) => {
console.log("reject", err);
}
);
複制代碼
複制
總結
經過如上步驟,隻完成了Promise的基本操作,