promise專題--手寫promise03
上篇回顧
promise專題–手寫promise02
上篇我們解決了非同步呼叫的問題,但是發現鏈式呼叫是行不通的。這篇解決這個問題。
一、問題分析
原生promise為什麼支援then的鏈式呼叫?因為原生每次then之後會返回一個promise物件,所以可以支援鏈式呼叫,但是上篇我們寫的並沒有返回一個promise物件,所以當我們再then的時候,就是undefined.then,所以理所當然直接報錯嘍,所以鏈式呼叫的核心就是要返回一個promise物件,下面看怎麼做!
二、重寫then方法
1、因為要返回一個promise物件,所以我們直接搭建新的程式碼框架,具體為
Promise.prototype.then = function (onFulfilled, onRejected) {
let newPromise = new Promise((resolve, reject) => {})
return newPromise ;
}
2、重寫上一篇的三種情況,因為每次返回一個promise,所以我們得知道上一個執行的到底是成功了還是失敗了,所以當拿到結果的時候我們需要一個方法來解析這個promise到底是成功了還是失敗了。
Promise.prototype.then = function (onFulfilled, onRejected) {
let newPromise = new Promise((resolve, reject) => {
if (_this.status === "fulfilled") {
setTimeout(() => {
// 需要使用newPromise,所以需要放入非同步程式碼中
try {
let res = onFulfilled(_this.successValue);
//resolve(res);
// 對res進行解析判斷
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
}
})
return newPromise ;
}
function resolvePromise(promise,res, resolve, reject) {
// 這裡需要判斷一個迴圈引用的問題
if (res === promise) {
return reject(new TypeError("迴圈引用!"));
}
// 判斷是否是一個物件或者函式
if (res != null && typeof res === 'object' || typeof res === 'function') {
// 判斷是否是promise
try {
let then = res.then; // then有可能丟擲異常
if (typeof then === 'function') {
// 將其認為是一個promise,然後執行then
then.call(res, (y) => {
resolve(y);
}, (r) => {
reject(r);
});
} else {
// 認為是一個普通的值
resolve(res);
}
}catch (e) {
reject(e);
}
} else {
// 非引用型別 也就是一個普通值
resolve(res);
}
}
3、失敗和非同步的重寫如下,整體程式碼如下:
Promise.prototype.then = function (onFulfilled, onRejected) {
let _this = this;
// then被執行,需要再次返回一個新的promise例項
// 需要拿到當前then方法的結果也就是得知道成功或者失敗
let newPromise = new Promise((resolve, reject) => {
if (_this.status === "fulfilled") {
setTimeout(() => {
// 需要使用promise2,所以需要放入非同步程式碼中
try {
let res = onFulfilled(_this.successValue);
//resolve(res);
// 對res進行解析判斷
resolvePromise(newPromise, res, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
}
if (_this.status === "rejected") {
setTimeout(() => {
try {
let res = onRejected(_this.errReason);
resolvePromise(newPromise, res, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
}
if (_this.status === "pending") {
_this.onResolvedCallbacks.push(function () {
setTimeout(() => {
try {
let res = onFulfilled(_this.successValue);
resolvePromise(newPromise, res, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
_this.onRejectedCallbacks.push(function () {
setTimeout(() => {
try {
let res = onRejected(_this.errReason);
resolvePromise(newPromise, res, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
})
}
});
return newPromise;
}
三、大體思路
1.能夠鏈式呼叫,肯定then方法最後需要返回一個Promise例項;
2. 在then方法中用res去接收成功或者失敗的返回值,當成功或失敗方法丟擲錯誤,直接執行reject。因為要分析成功或者失敗的回撥,所以專門抽出一個方法resolvePromise用來分析返回值;
3. resolvePromise方法中傳入了四個引數,then中的newPromise,res值;
4. 如果res與promise相等,說明重複引用了,直接報錯幹掉;
5. 當res不是null,是個物件型別or函式型別,並且他的then方法也是函式型別時,就可以認為res他是個promise例項,執行x.then()方法;再用resolvePromise方法分析他的成功的返回值即可;
6. 如果res不是null不是object或function,就可以將其認為一個普通值,執行resolve方法即可;
7. 如果res.then方法丟擲異常了,直接呼叫reject方法就ok嘍;
四、支援then穿透
原生promise支援then穿透也就是
p.then().then().then(()= > {....})
如何實現?
思路: then方法返回執行promise前,判斷下,如果是穿透的話,返回的不是一個function型別,處理下就ok
Promise.prototype.then = function (onFulfilled, onRejected) {
// 穿透處理
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason
}
.......
}
下一篇實現all, race, resolve,reject,catch,finally方法
相關文章
- 手寫 PromisePromise
- 手寫PromisePromise
- Promise規範以及手寫PromisePromise
- 嘗試手寫promisePromise
- 手寫簡易PromisePromise
- 自己動手寫PromisePromise
- 手寫一個PromisePromise
- 基於promise /A+規範手寫promisePromise
- Promise學習筆記(知識點 + 手寫Promise)Promise筆記
- 手寫 Promise 詳細解讀Promise
- 從頭手寫一個PromisePromise
- 手寫一個自己的PromisePromise
- 手寫一個自定義PromisePromise
- 手寫實現滿足 Promise/A+ 規範的 PromisePromise
- 純手寫Promise,由淺入深Promise
- 用原生js手寫實現promiseJSPromise
- 從手寫一個符合Promise/A+規範Promise來深入學習PromisePromise
- 初識Promise並手寫符合PromiseA+規範的PromisePromise
- 你也可以手寫自己的Promise(一)Promise
- 手寫一個Promise,附原始碼分析Promise原始碼
- 手寫promise,瞭解一下(二)Promise
- 前端面試考點之---手寫Promise前端面試Promise
- 手寫promise,瞭解一下(一)Promise
- 這篇手寫 Promise 你一定要康康Promise
- 史上最最最詳細的手寫Promise教程Promise
- Promise拆解計劃:手寫Promise並透過官方全部測試用例Promise
- BAT前端經典面試問題:史上最最最詳細的手寫Promise教程BAT前端面試Promise
- 最最最通俗易懂的promise手寫系列(一)Promise
- 一步一步實現手寫PromisePromise
- 手寫面試題面試題
- js 真的是一步一步手寫promiseJSPromise
- 手寫Promise中then方法返回的結果或者規律Promise
- 手寫Promise看著一篇就足夠了Promise
- 一個下課的時間帶你手寫promise!Promise
- 面試官你來,130行帶你手寫完整Promise面試Promise
- [手寫系列] 帶你實現一個簡單的PromisePromise
- 手擼 Promise (then、catch)Promise
- [面試專題]JS非同步之Promise,Generator,Async面試JS非同步Promise