您好,登錄后才能下訂單哦!
這篇文章主要介紹了js中promise對(duì)象有什么用,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。
js中的異步,剛開(kāi)始的時(shí)候都是用回調(diào)函數(shù)實(shí)現(xiàn)的,所以如果異步嵌套的話(huà),就有出現(xiàn)回調(diào)地獄,使得代碼難以閱讀和難以維護(hù),后來(lái)es6出現(xiàn)了promise,解決了回調(diào)地獄的問(wèn)題?,F(xiàn)在我們就自己寫(xiě)代碼實(shí)現(xiàn)一下promise,這樣才能深入理解promise的運(yùn)行機(jī)制,對(duì)以后使用promise也能夠更加得心應(yīng)手。開(kāi)始之前可以先看下promise的官網(wǎng)promise/A+
先來(lái)看下promise的用法
new Promise((resolve,reject)=>{ resolve(1); reject(11); }).then(res=>{ console.log(res); setTimeout(()=>{ return new Promise((resolve,reject)=>{ resolve(2) }) },1000) }).then(res2=>{ console.log(res2); });
控制臺(tái)打印
1
...1s later
2
先分析下上面這段代碼,先提出幾個(gè)問(wèn)題
1.第一段resolve和reject都有,但是只輸出了1,為什么?
2.then里的res是如何取到resolve中的值的?
3.promise是如何做到鏈?zhǔn)秸{(diào)用的?
promise中有個(gè)狀態(tài)機(jī)的概念,先說(shuō)下為什么要有狀態(tài)機(jī)的概念呢,因?yàn)閜romise的狀態(tài)是單向變化的,有三種狀態(tài),pending,fullfilled,rejected,而這三種狀態(tài)只能從pending->fullfilled或者pending->rejected這兩種形式,也就是說(shuō)執(zhí)行了fullfilled之后,就不會(huì)執(zhí)行rejected。這就解釋了上面的第一個(gè)問(wèn)題。
下面我們來(lái)看下具體實(shí)現(xiàn)的完整代碼
const PENDING = 'PENDING'; const FULLFILLED = 'FULLFILLED'; const REJECTED = 'REJECTED'; class Promise{ constructor(fn){ this.status = PENDING;//狀態(tài) this.data = undefined;//返回值 this.defercb = [];//回調(diào)函數(shù)數(shù)組 //執(zhí)行promise的參數(shù)函數(shù),并把resolve和reject的this綁定到promise的this fn(this.resolve.bind(this),this.reject.bind(this)); } resolve(value){ if(this.status === PENDING){ //只能pending=>fullfied this.status = FULLFILLED; this.data = value; this.defercb.map(item=>item.onFullFilled()); } } reject(value){ if(this.status === PENDING){ //只能pending=>rejected this.status = REJECTED; this.data = value; this.defercb.map(item=>item.onRejected()); } } then(resolveThen,rejectThen){ //如果沒(méi)有resolveThen方法,保證值可以穿透到下一個(gè)then里有resolveThen的方法中 resolveThen = typeof resolveThen === 'function' ? resolveThen : function(v) {return v}; rejectThen = typeof rejectThen === 'function' ? rejectThen : function(r) {return r}; //返回的都是promise對(duì)象,這樣就可以保證鏈?zhǔn)秸{(diào)用了 switch(this.status){ case PENDING: return new Promise((resolve,reject)=>{ const onFullFilled = () => { const result = resolveThen(this.data);//這里調(diào)用外部then的resolveThen方法,將值傳回去 //如果返回值是promise對(duì)象,執(zhí)行then方法,取它的結(jié)果作為新的promise實(shí)例的結(jié)果,因?yàn)閠his.data會(huì)重新賦值 result instanceof Promise && result.then(resolve,reject); } const onRejected = ()=>{ const result = rejectThen(this.data); result instanceof Promise && result.then(resolve,reject); } this.defercb.push({onFullFilled,onRejected}); }); break; case FULLFILLED: return new Promise((resolve,reject)=>{ const result = resolveThen(this.data); result instanceof Promise && result.then(resolve,reject); resolve(result); }) break; case REJECTED: return new Promise((resolve,reject)=>{ const result = rejectThen(this.data); result instanceof Promise && result.then(resolve,reject); reject(result) }) break; } } }
運(yùn)行下面的例子
new Promise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }).then((res2) => { console.log(res2); return new Promise((resolve, reject) => { setTimeout(() => { resolve(2); }, 1000); }); }).then((res3) => { console.log(res3); return new Promise((resolve, reject) => { setTimeout(() => { resolve(3); }, 1000); }); }).then((res4) => { console.log(res4); });
控制臺(tái)打印
...1s later
1
...1s later
2
...1s later
3
說(shuō)明上面的實(shí)現(xiàn)是沒(méi)有問(wèn)題的
不過(guò)還有一個(gè)問(wèn)題,就是事件循環(huán)的順序問(wèn)題,比如執(zhí)行下面的代碼
new Promise((resolve) => { resolve(); }) .then(() => { console.log('1'); }) .then(() => { console.log('2'); }); console.log('3');
并沒(méi)有像預(yù)想中輸出3,1,2,而是輸出了1,2,3,原因就是因?yàn)槲覀兊倪@個(gè)Promise是在主線程中,沒(méi)有在下一個(gè)任務(wù)隊(duì)列中,可以加上settimeout解決這個(gè)問(wèn)題,不過(guò)這也只是為了讓我們更好理解執(zhí)行順序而已,然而實(shí)際上是promise是屬于微任務(wù)中的,而settimeout是屬于宏任務(wù),還是不太一樣的
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享js中promise對(duì)象有什么用內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,遇到問(wèn)題就找億速云,詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。