2022-12-02
mypromise
引子
面試時如果被問到“如果沒有Promise,能不能自己實現(xiàn)一個”,就是在深度考察對異步的理解了;
如果你的回答是“能,我封過”,則必然令人刮目相看~
事實上,作為ES6新增的API,即使沒有,用戶也完全可以基于想要的效果自己去實現(xiàn)一個;
這里給到大家我個人的實現(xiàn):MyPromise;
源碼地址
實現(xiàn)思路
將then/catch/finally中入?yún)⒌幕卣{(diào)函數(shù)按順序收集到一個隊列中;
親自實現(xiàn)一下resolve和reject方法;
一旦實例resolve就將隊列頭部的catch回調(diào)都彈出,一旦實例reject就將隊列頭部的then回調(diào)都彈出,然后拿取隊列頭部的回調(diào)函數(shù)實行起來;
每次回調(diào)的執(zhí)行結(jié)果即返回值需要繼續(xù)resolve或reject一下,然后繼續(xù)遞歸執(zhí)行上述過程,直到回調(diào)隊列為空;
接收任務(wù)執(zhí)行器
當(dāng)我們new出一個MyPromise,并內(nèi)置一個任務(wù)執(zhí)行器函數(shù)的時候,需要在MyPromise的構(gòu)造器中接收任務(wù)執(zhí)行器函數(shù),并同步地、立即地將其執(zhí)行起來;
要特別注意:任務(wù)執(zhí)行器函數(shù)是同步地跑在主線程的,而不屬于異步回調(diào);
test.js
new MyPromise(
/* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */
(resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve("data0") : reject(new Error("一張好人卡"));
}, 2000);
}
)
MyPromise.js
class MyPromise {
constructor(executor) {
/* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */
this.executor = executor;
this.executor();
}
}
定義resolve與reject
任務(wù)執(zhí)行器函數(shù)會在稍后履約(resolve)或毀約(reject)
因此要告訴MyPromise履約或毀約時具體做什么
這里我們先做一下簡單的打印
MyPromise.js
class MyPromise {
constructor(executor) {
/* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */
/* 綁定執(zhí)行器函數(shù)中的resolve與reject */
this.executor = executor.bind(
this, //當(dāng)前promise實例
//當(dāng)前promise實例執(zhí)行resolve時,this不變
MyPromise.doResolve.bind(this),
//當(dāng)前promise實例執(zhí)行reject時,this不變
MyPromise.doReject.bind(this)
);
this.executor();
}
/* promise實例執(zhí)行resolve */
static doResolve(data) {
console.log("doResolve", data);
}
/* promise實例執(zhí)行reject */
static doReject(err) {
console.log("doReject", err);
}
}
module.exports = MyPromise;
明確回調(diào)期望
明確一下異步任務(wù)履約/毀約后我們希望做什么
我們希望一旦異步任務(wù)resolve就執(zhí)行then中的回調(diào)
我們希望一旦異步任務(wù)reject就執(zhí)行catch中的回調(diào)
我們希望異步任務(wù)無論成功還是失敗,最終都執(zhí)行finally中的回調(diào)
期望如下:test.js
const MyPromise = require("./MyPromiseX")
new MyPromise(
/* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */
(resolve, reject) => {
setTimeout(() => {
Math.random() > 0.1 ? resolve("data0") : reject(new Error("一張好人卡"));
}, 2000);
}
)
.then(
data => {
console.log("then1:data=",data)
return "data from then1"
// throw new Error("err from then1")
}
)
.catch(
err => {
console.log("catch1:err=",err)
return "data from catch1"
}
)
.finally(
()=>console.log("finally:game over!")
)
收集回調(diào)隊列
每一個then中有一個成功回調(diào)
每一個catch中有一個失敗回調(diào)
finally中有一個最終回調(diào)
我們先按順序?qū)⑦@些回調(diào)收集在一個隊列中
代碼如下:MyPromise.js
class MyPromise {
constructor(executor) {
// 回調(diào)隊列
this.callbacks = [];
/* 接收任務(wù)執(zhí)行器并立即調(diào)用(同步調(diào)用) */
// 綁定執(zhí)行器函數(shù)中的resolve與reject
this.executor = executor.bind(
this, //當(dāng)前promise實例
//當(dāng)前promise實例執(zhí)行resolve時,this不變
MyPromise.doResolve.bind(this),
//當(dāng)前promise實例執(zhí)行reject時,this不變
MyPromise.doReject.bind(this)
);
// 立即調(diào)用任務(wù)執(zhí)行器
this.executor();
}
/* promise實例執(zhí)行resolve */
static doResolve(data) {
console.log("doResolve", data);
}
/* promise實例執(zhí)行reject */
static doReject(err) {
console.log("doReject", err);
}
/* 收集成功回調(diào)到隊列 */
then(onData) {
// 將來一旦Promise毀約 回調(diào)隊列頭部的所有then回調(diào)都要彈出作廢
this.callbacks.push({ type: "then", callback: onData });
return this;
}
/* 收集失敗回調(diào)到隊列 */
catch(onErr) {
// 將來一旦Promise履約 回調(diào)隊列頭部的所有catch回調(diào)都要彈出作廢
this.callbacks.push({ type: "catch", callback: onErr });
return this;
}
/* 收集終點回調(diào)到隊列(此處假設(shè)只有一個終點回調(diào)) */
finally(onFinish) {
this.callbacks.push({ type: "finally", callback: onFinish });
return this;
}
}
module.exports = MyPromise;
此時在測試腳本test.js的末尾打印一下回調(diào)隊列的話,你會看到如下輸出:
[
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'catch', callback: [Function (anonymous)] },
{ type: 'finally', callback: [Function (anonymous)] }
]
如果來上一堆亂序的then/catch/finally的話,則你會看到如下輸出:
[
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'catch', callback: [Function (anonymous)] },
{ type: 'catch', callback: [Function (anonymous)] },
{ type: 'then', callback: [Function (anonymous)] },
{ type: 'finally', callback: [Function (anonymous)] }
]
連環(huán)作案(履約或毀約)
讓我們在每次成功或失敗后,都隨機地繼續(xù)履約或毀約起來!
test.js
const MyPromise = require("./MyPromiseX")
const p = new MyPromise(
/* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */
(resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve("data0") : reject(new Error("一張好人卡"));
}, 2000);
}
)
.then(
data => {
console.log("then1:data=",data)
/* 繼續(xù)履約或毀約! */
return "data from then1"
// throw new Error("err from then1")
}
)
.then(
data => {
console.log("then2:data=",data)
/* 繼續(xù)履約或毀約! */
return MyPromise.resolve("data from then2")
// return MyPromise.reject("err from then2")
}
)
.then(
data => {
console.log("then3:data=",data)
/* 繼續(xù)履約或毀約! */
return new MyPromise(
(resolve,reject) => setTimeout(() => {
resolve("data from then3")
// reject("err from then3")
}, 2000)
)
}
)
.then(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
data => console.log("then4:data=",data)
)
.catch(
err => {
console.log("catch1:err=",err)
/* 繼續(xù)履約 */
return "data from catch1"
}
)
.catch(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
err => console.log("catch2:err=",err)
)
.then(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
data => console.log("then5:data=",data)
)
.finally(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
()=>console.log("finally:game over!")
)
// 打印一下MyPromise對象的回調(diào)隊列
console.log("p.callbacks",p.callbacks);
所謂MyPromise.resolve(data)或MyPromise.reject(err)無非也就是newPromise(executor)的一個語法糖而已,實現(xiàn)如下:
MyPromise.js片段
/* 語法糖:創(chuàng)建一個立即resolve的Promise對象 */
static resolve(data) {
return new MyPromise((resolve) => resolve(data));
}
/* 語法糖:創(chuàng)建一個立即reject的Promise對象 */
static reject(err) {
return new MyPromise((resolve, reject) => reject(err));
}
準(zhǔn)備執(zhí)行連環(huán)回調(diào)
我們無非想要如下效果:
只要前面的環(huán)節(jié)履約了:在回調(diào)隊列中找出下一個type為then的回調(diào)執(zhí)行起來;
只要前面的環(huán)節(jié)毀約了:在回調(diào)隊列中找出下一個type為catch的回調(diào)執(zhí)行起來;
找下一個then回調(diào)前,所有位于它前面的catch都驅(qū)逐先;
找下一個catch回調(diào)前,所有位于它前面的then都驅(qū)逐先;
我們來擼碼實現(xiàn)之!
定義MyPromise狀態(tài)
class MyPromise {
/* Promise狀態(tài)定義 */
static STATUS_PENDING = 0; // 掛起態(tài)
static STATUS_FULFILLED = 1; // 履約態(tài)
static STATUS_REJECTED = 2; // 毀約態(tài)
...
}
定義回調(diào)入?yún)?/p>
constructor(executor) {
/* 回調(diào)隊列 + 回調(diào)入?yún)?(JS單線程模型=每次只能有一個回調(diào)被執(zhí)行) */
this.callbacks = [];
// 定義給回調(diào)傳的入?yún)ⅲ瑹o論是數(shù)據(jù)還是錯誤,我們統(tǒng)稱為cbArg
this.cbArg = null;
...
}
定義驅(qū)逐器
成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐
失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐
/*
成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐
失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐
*/
shiftCallbacksWithType(type) {
/* 只要回調(diào)隊列中還有回調(diào),就把隊列頭部type為指定類型的回調(diào)彈出去 */
while (this.callbacks.length && this.callbacks[0].type === type) {
// 驅(qū)逐一個回調(diào)函數(shù)
this.callbacks.shift();
}
}
執(zhí)行連環(huán)回調(diào)
當(dāng)前任履約時
狀態(tài)設(shè)置為履約態(tài)
將回調(diào)入?yún)⒃O(shè)置為需要履約的數(shù)據(jù)
找下一個then里的回調(diào)執(zhí)行起來
/* promise實例執(zhí)行resolve */
static doResolve(data) {
/* 設(shè)置狀態(tài)為履約態(tài) + 設(shè)置回調(diào)時的入?yún)?+ 拉起下一次回調(diào) */
this.status = MyPromise.STATUS_FULFILLED;
// 回調(diào)入?yún)閿?shù)據(jù)
this.cbArg = data;
// 拉起下一次then回調(diào)
setTimeout(() => {
this.next();
});
}
當(dāng)前任毀約時
狀態(tài)設(shè)置為毀約態(tài)
將回調(diào)入?yún)⒃O(shè)置為毀約的原因
找下一個catch里的回調(diào)執(zhí)行起來
/* promise實例執(zhí)行reject */
static doReject(err) {
/* 設(shè)置狀態(tài)為毀約態(tài) + 設(shè)置回調(diào)時的錯誤 + 拉起下一次回調(diào) */
this.status = MyPromise.STATUS_REJECTED;
// 回調(diào)入?yún)殄e誤
this.cbArg = err;
// 拉起下一次catch回調(diào)
setTimeout(() => {
this.next();
});
}
執(zhí)行下一次回調(diào)
整個MyPromise最核心的邏輯來了
只要當(dāng)前MyPromise為履約態(tài),就驅(qū)逐隊列頭部所有的catch回調(diào)先
只要當(dāng)前MyPromise為毀約態(tài),就驅(qū)逐隊列頭部所有的then回調(diào)先
拿取隊列頭部的那個回調(diào)執(zhí)行起來
next() {
/* 確定該回調(diào)哪一個callback */
if (this.status === MyPromise.STATUS_FULFILLED) {
// 履約時:彈光隊列頭部的catch回調(diào)
this.shiftCallbacksWithType("catch");
}
if (this.status === MyPromise.STATUS_REJECTED) {
// 毀約時:彈光隊列頭部的then回調(diào)
this.shiftCallbacksWithType("then");
}
/* 如果回調(diào)隊列已空,則直接結(jié)束程序 */
if (!this.callbacks.length) {
console.log("回調(diào)隊列已空");
return;
}
/* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */
let { callback } = this.callbacks.shift();
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
}
當(dāng)回調(diào)返回value
test.js片段
.then(
data => {
console.log("then1:data=",data)
/* 繼續(xù)履約或毀約! */
return "data from then1"
// throw new Error("err from then1")
}
)
當(dāng)回調(diào)返回一個新的(非MyPromise對象)的普通value時,我們繼續(xù)向后resolve它
程序會繼續(xù)doResolve,doResolve內(nèi)部會繼續(xù)拉起下一次next
下一次next找出的回調(diào)還有新的返回值
遞歸了解一下!歸了解一下!了解一下!解一下!一下!下!
next() {
...
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
/* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */
if (!(value instanceof MyPromise)) {
MyPromise.doResolve.call(this, value);
}
...
}
當(dāng)回調(diào)拋出錯誤時
test.js片段
.then(
data => {
console.log("then1:data=",data)
/* 繼續(xù)履約或毀約! */
// return "data from then1"
throw new Error("err from then1")
}
)
try-catch起來,把錯誤信息reject一下
程序會繼續(xù)doReject,doReject內(nèi)部會繼續(xù)拉起下一次next
下一次next找出的回調(diào)還有新的返回值
遞歸了解一下!歸了解一下!了解一下!解一下!一下!下!
next() {
...
/* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */
let { callback } = this.callbacks.shift();
/* 防止回調(diào)函數(shù)中throw錯誤 */
try {
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
/* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */
if (!(value instanceof MyPromise)) {
MyPromise.doResolve.call(this, value);
}else {
...
}
} catch (err) {
// 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)
MyPromise.doReject.call(this, err);
}
}
當(dāng)回調(diào)返回一個新的MP對象時
.then(
data => {
console.log("then2:data=",data)
/* 繼續(xù)履約或毀約! */
return MyPromise.resolve("data from then2")
// return MyPromise.reject("err from then2")
}
)
.then(
data => {
console.log("then3:data=",data)
/* 繼續(xù)履約或毀約! */
return new MyPromise(
(resolve,reject) => setTimeout(() => {
resolve("data from then3")
// reject("err from then3")
}, 2000)
)
}
)
首先,MP的構(gòu)造器一定會被調(diào)用!
構(gòu)造器里有this.executor(),this.executor()里有resolve(data)或reject(err),也就是doResolve(data)或doReject(err)
不斷遞歸next()找下一次回調(diào)的過程會自發(fā)地跑起
這個該死的MP對象可能自帶一個回調(diào)隊列
我們把當(dāng)前MP對象剩余的回調(diào)隊列過戶給它即可
next() {
...
/* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */
let { callback } = this.callbacks.shift();
/* 防止回調(diào)函數(shù)中throw錯誤 */
try {
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
/* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */
if (!(value instanceof MyPromise)) {
...
}
else {
// 如果回調(diào)函數(shù)返回一個Promise對象
// 將后續(xù)所有callback過戶給新的Promise對象
value.callbacks = value.callbacks.concat(this.callbacks);
}
} catch (err) {...}
}
完整的next函數(shù)
遞歸inside!
/*
從回調(diào)隊列里拉取下一個適當(dāng)?shù)腸allback并回調(diào)之
這是MyPromise的核心代碼:遞歸inside!
*/
next() {
/* 確定該回調(diào)哪一個callback */
if (this.status === MyPromise.STATUS_FULFILLED) {
// 履約時:彈光隊列頭部的catch回調(diào)
this.shiftCallbacksWithType("catch");
}
if (this.status === MyPromise.STATUS_REJECTED) {
// 毀約時:彈光隊列頭部的then回調(diào)
this.shiftCallbacksWithType("then");
}
/* 如果回調(diào)隊列已空,則直接結(jié)束程序 */
if (!this.callbacks.length) {
console.log("回調(diào)隊列已空");
return;
}
/* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */
let { callback } = this.callbacks.shift();
/* 防止回調(diào)函數(shù)中throw錯誤 */
try {
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
/* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */
if (!(value instanceof MyPromise)) {
MyPromise.doResolve.call(this, value);
}
else {
// 如果回調(diào)函數(shù)返回一個Promise對象
// 將后續(xù)所有callback過戶給新的Promise對象
value.callbacks = value.callbacks.concat(this.callbacks);
}
} catch (err) {
// 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)
MyPromise.doReject.call(this, err);
}
}
完整代碼
MyPromise.js
class MyPromise {
/* Promise狀態(tài)定義 */
static STATUS_PENDING = 0; // 掛起態(tài)
static STATUS_FULFILLED = 1; // 履約態(tài)
static STATUS_REJECTED = 2; // 毀約態(tài)
constructor(executor) {
/* 回調(diào)隊列 + 回調(diào)入?yún)?(JS單線程模型=每次只能有一個回調(diào)被執(zhí)行) */
this.callbacks = [];
// 定義給回調(diào)傳的入?yún)ⅲ瑹o論是數(shù)據(jù)還是錯誤,我們統(tǒng)稱為cbArg
this.cbArg = null;
/* 綁定執(zhí)行器函數(shù)中的resolve與reject */
this.executor = executor.bind(
this, //當(dāng)前promise實例
//當(dāng)前promise實例執(zhí)行resolve時,this不變
MyPromise.doResolve.bind(this),
//當(dāng)前promise實例執(zhí)行reject時,this不變
MyPromise.doReject.bind(this)
);
// 執(zhí)行任務(wù)前先將Promise狀態(tài)設(shè)置為pending
this.status = MyPromise.STATUS_PENDING;
// 執(zhí)行任務(wù)(任務(wù)中會resolve/doResolve或reject/doReject)
this.executor();
}
/* promise實例執(zhí)行resolve */
static doResolve(data) {
/* 設(shè)置狀態(tài)為履約態(tài) + 設(shè)置回調(diào)時的入?yún)?+ 拉起下一次回調(diào) */
this.status = MyPromise.STATUS_FULFILLED;
// 回調(diào)入?yún)閿?shù)據(jù)
this.cbArg = data;
// 拉起下一次then回調(diào)
setTimeout(() => {
this.next();
});
}
/* promise實例執(zhí)行reject */
static doReject(err) {
/* 設(shè)置狀態(tài)為毀約態(tài) + 設(shè)置回調(diào)時的錯誤 + 拉起下一次回調(diào) */
this.status = MyPromise.STATUS_REJECTED;
// 回調(diào)入?yún)殄e誤
this.cbArg = err;
// 拉起下一次catch回調(diào)
setTimeout(() => {
this.next();
});
}
/*
成功時:從回調(diào)隊列頭部把所有的catch驅(qū)逐
失敗時:從回調(diào)隊列頭部把所有的then驅(qū)逐
*/
shiftCallbacksWithType(type) {
/* 只要回調(diào)隊列中還有回調(diào),就把隊列頭部type為指定類型的回調(diào)彈出去 */
while (this.callbacks.length && this.callbacks[0].type === type) {
// 驅(qū)逐一個回調(diào)函數(shù)
this.callbacks.shift();
}
}
/*
從回調(diào)隊列里拉取下一個適當(dāng)?shù)腸allback并回調(diào)之
這是MyPromise的核心代碼:遞歸inside!
*/
next() {
/* 確定該回調(diào)哪一個callback */
if (this.status === MyPromise.STATUS_FULFILLED) {
// 履約時:彈光隊列頭部的catch回調(diào)
this.shiftCallbacksWithType("catch");
}
if (this.status === MyPromise.STATUS_REJECTED) {
// 毀約時:彈光隊列頭部的then回調(diào)
this.shiftCallbacksWithType("then");
}
/* 如果回調(diào)隊列已空,則直接結(jié)束程序 */
if (!this.callbacks.length) {
console.log("回調(diào)隊列已空");
return;
}
/* 拉取回調(diào)隊列頭部的回調(diào)函數(shù)(注意這里無視了type只解構(gòu)出函數(shù)本身) */
let { callback } = this.callbacks.shift();
/* 防止回調(diào)函數(shù)中throw錯誤 */
try {
// 執(zhí)行回調(diào)并拿到其結(jié)果(value或promise對象)
let value = callback(this.cbArg);
/* 如果回調(diào)函數(shù)返回一個value 繼續(xù)向下resolve(value) */
if (!(value instanceof MyPromise)) {
MyPromise.doResolve.call(this, value);
}
else {
// 如果回調(diào)函數(shù)返回一個Promise對象
// 將后續(xù)所有callback過戶給新的Promise對象
value.callbacks = value.callbacks.concat(this.callbacks);
}
} catch (err) {
// 回調(diào)函數(shù)拋出錯誤時相當(dāng)于reject(err)
MyPromise.doReject.call(this, err);
}
}
/* 語法糖:創(chuàng)建一個立即resolve的Promise對象 */
static resolve(data) {
return new MyPromise((resolve) => resolve(data));
}
/* 語法糖:創(chuàng)建一個立即reject的Promise對象 */
static reject(err) {
return new MyPromise((resolve, reject) => reject(err));
}
/* 收集成功回調(diào)到隊列 */
then(onData) {
// 將來一旦Promise毀約 回調(diào)隊列頭部的所有then回調(diào)都要彈出作廢
this.callbacks.push({ type: "then", callback: onData });
return this;
}
/* 收集失敗回調(diào)到隊列 */
catch(onErr) {
// 將來一旦Promise履約 回調(diào)隊列頭部的所有catch回調(diào)都要彈出作廢
this.callbacks.push({ type: "catch", callback: onErr });
return this;
}
/* 收集終點回調(diào)到隊列(此處假設(shè)只有一個終點回調(diào)) */
finally(onFinish) {
this.callbacks.push({ type: "finally", callback: onFinish });
return this;
}
}
module.exports = MyPromise;
測試代碼test.js
const MyPromise = require("./MyPromise3")
const p = new MyPromise(
/* 任務(wù)執(zhí)行器:2秒后隨機履約或毀約 */
(resolve, reject) => {
setTimeout(() => {
Math.random() > 0.1 ? resolve("data0") : reject(new Error("一張好人卡"));
}, 2000);
}
)
.then(
data => {
console.log("then1:data=",data)
/* 繼續(xù)履約或毀約! */
return "data from then1"
// throw new Error("err from then1")
}
)
.then(
data => {
console.log("then2:data=",data)
/* 繼續(xù)履約或毀約! */
return MyPromise.resolve("data from then2")
// return MyPromise.reject("err from then2")
}
)
.then(
data => {
console.log("then3:data=",data)
/* 繼續(xù)履約或毀約! */
return new MyPromise(
(resolve,reject) => setTimeout(() => {
resolve("data from then3")
// reject("err from then3")
}, 2000)
)
}
)
.then(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
data => console.log("then4:data=",data)
)
.catch(
err => {
console.log("catch1:err=",err)
/* 繼續(xù)履約 */
return "data from catch1"
}
)
.catch(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
err => console.log("catch2:err=",err)
)
.then(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
data => console.log("then5:data=",data)
)
.finally(
/* 這里本質(zhì)繼續(xù)履約了一個undefined */
()=>console.log("finally:game over!")
)
// 打印一下MyPromise對象的回調(diào)隊列
console.log("p.callbacks",p.callbacks);
測試效果
https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5c47910678fd41acba1eed2ea02bbabb~tplv-k3u1fbpfcp-watermark.image?
開班時間:2021-04-12(深圳)
開班盛況開班時間:2021-05-17(北京)
開班盛況開班時間:2021-03-22(杭州)
開班盛況開班時間:2021-04-26(北京)
開班盛況開班時間:2021-05-10(北京)
開班盛況開班時間:2021-02-22(北京)
開班盛況開班時間:2021-07-12(北京)
預(yù)約報名開班時間:2020-09-21(上海)
開班盛況開班時間:2021-07-12(北京)
預(yù)約報名開班時間:2019-07-22(北京)
開班盛況Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right 京ICP備12003911號-5 京公網(wǎng)安備 11010802035720號