摘要:本文博客原文地址我們在開發(fā)過程中大多會(huì)用到,想必大家對(duì)的使用都很熟練了,今天我們就來實(shí)現(xiàn)一個(gè)簡單的,實(shí)現(xiàn)的效果如有出入還往指正。對(duì)象的狀態(tài)不受外界影響。對(duì)象代表一個(gè)異步操作,有三種狀態(tài)進(jìn)行中已成功和已失敗。
本文博客原文地址
我們在開發(fā)過程中大多會(huì)用到promise,想必大家對(duì)promise的使用都很熟練了,今天我們就來實(shí)現(xiàn)一個(gè)簡單的promise,實(shí)現(xiàn)的效果如有出入還往指正。
整體結(jié)構(gòu)我們先來梳理一下整體的結(jié)果,以便后續(xù)好操作
class MyPromise { constructor(fn){ } resolve(){ } then(){ } reject(){ } catch(){ } }Promise理論知識(shí)
摘抄至 http://es6.ruanyifeng.com/#do...
Promise對(duì)象有以下兩個(gè)特點(diǎn)。
(1)對(duì)象的狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個(gè)狀態(tài)。這也是Promise這個(gè)名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。
(2)一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。Promise對(duì)象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會(huì)再變了,會(huì)一直保持這個(gè)結(jié)果,這時(shí)就稱為 resolved(已定型)。如果改變已經(jīng)發(fā)生了,你再對(duì)Promise對(duì)象添加回調(diào)函數(shù),也會(huì)立即得到這個(gè)結(jié)果。這與事件(Event)完全不同,事件的特點(diǎn)是,如果你錯(cuò)過了它,再去監(jiān)聽,是得不到結(jié)果的。
總結(jié)一下就是promise有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失敗),還有就是狀態(tài)的改變只能是pending -> fulfilled 或者 pending -> rejected,這些很重要
實(shí)現(xiàn)構(gòu)造函數(shù)現(xiàn)在我們開始實(shí)現(xiàn)構(gòu)造函數(shù)
class MyPromise { constructor(fn){ if(typeof fn !== "function") { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = "pending"; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } ... }
構(gòu)造函數(shù)接收一個(gè)參數(shù)fn,且這個(gè)參數(shù)必須是一個(gè)函數(shù),因?yàn)槲覀円话氵@樣使用new Promise((resolve,reject)=>{});
然后初始化一下promise的狀態(tài),默認(rèn)開始為pending,初始化value的值。
fn接收兩個(gè)參數(shù),resolve、reject
class MyPromise { constructor(fn){ if(typeof fn !== "function") { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = "pending"; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== "pending") return; this.state = "fulfilled"; this.value = value } ... }
當(dāng)resolve執(zhí)行,接收到一個(gè)值之后;狀態(tài)就由 pending -> fulfilled;當(dāng)前的值為接收的值
rejectclass MyPromise { constructor(fn){ if(typeof fn !== "function") { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = "pending"; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== "pending") return; this.state = "fulfilled"; this.value = value } reject(reason){ if(this.state !== "pending") return; this.state = "rejected"; this.value = reason } }
當(dāng)reject執(zhí)行,接收到一個(gè)值之后;狀態(tài)就由 pending -> rejected;當(dāng)前的值為接收的值
thenclass MyPromise { constructor(fn){ if(typeof fn !== "function") { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = "pending"; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== "pending") return; this.state = "fulfilled"; this.value = value } reject(reason){ if(this.state !== "pending") return; this.state = "rejected"; this.value = reason } then(fulfilled,rejected){ if (typeof fulfilled !== "function" && typeof rejected !== "function" ) { return this; } if (typeof fulfilled !== "function" && this.state === "fulfilled" || typeof rejected !== "function" && this.state === "rejected") { return this; } return new MyPromise((resolve,reject)=>{ if(fulfilled && typeof fulfilled === "function" && this.state === "fulfilled"){ let result = fulfilled(this.value); if(result && typeof result.then === "function"){ return result.then(resolve,reject) }else{ resolve(result) } } if(rejected && typeof rejected === "function" && this.state === "rejected"){ let result = rejected(this.value); if(result && typeof result.then === "function"){ return result.then(resolve,reject) }else{ resolve(result) } } }) } }
then的實(shí)現(xiàn)比較關(guān)鍵,首先有兩個(gè)判斷,第一個(gè)判斷傳的兩個(gè)參數(shù)是否都是函數(shù),如果部不是return this執(zhí)行下一步操作。
第二個(gè)判斷的作用是,比如,現(xiàn)在狀態(tài)從pending -> rejected;但是中間代碼中有許多個(gè).then的操作,我們需要跳過這些操作執(zhí)行.catch的代碼。如下面的代碼,執(zhí)行結(jié)果只會(huì)打印1
new Promise((resolve,reject)=>{ reject(1) }).then(()=>{ console.log(2) }).then(()=>{ console.log(3) }).catch((e)=>{ console.log(e) })
我們繼續(xù),接下來看到的是返回了一個(gè)新的promise,真正then的實(shí)現(xiàn)的確都是返回一個(gè)promise實(shí)例。這里不多說
下面有兩個(gè)判斷,作用是判斷是rejected還是fulfilled,首先看fulfilled,如果是fulfilled的話,首先執(zhí)行fulfilled函數(shù),并把當(dāng)前的value值傳過去,也就是下面這步操作,res就是傳過去的value值,并執(zhí)行了(res)=>{console.log(res)}這段代碼;執(zhí)行完成之后我們得到了result;也就是2這個(gè)結(jié)果,下面就是判斷當(dāng)前結(jié)果是否是一個(gè)promise實(shí)例了,也就是下面注釋了的情況,現(xiàn)在我們直接執(zhí)行resolve(result);
new Promise((resolve,reject)=>{ resolve(1) }).then((res)=>{ console.log(res) return 2 //return new Promise(resolve=>{}) })
剩下的就不多說了,可以debugger看看執(zhí)行結(jié)果
catchclass MyPromise { ... catch(rejected){ return this.then(null,rejected) } }完整代碼
class MyPromise { constructor(fn){ if(typeof fn !== "function") { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = "pending"; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== "pending") return; this.state = "fulfilled"; this.value = value } reject(reason){ if(this.state !== "pending") return; this.state = "rejected"; this.value = reason } then(fulfilled,rejected){ if (typeof fulfilled !== "function" && typeof rejected !== "function" ) { return this; } if (typeof fulfilled !== "function" && this.state === "fulfilled" || typeof rejected !== "function" && this.state === "rejected") { return this; } return new MyPromise((resolve,reject)=>{ if(fulfilled && typeof fulfilled === "function" && this.state === "fulfilled"){ let result = fulfilled(this.value); if(result && typeof result.then === "function"){ return result.then(resolve,reject) }else{ resolve(result) } } if(rejected && typeof rejected === "function" && this.state === "rejected"){ let result = rejected(this.value); if(result && typeof result.then === "function"){ return result.then(resolve,reject) }else{ resolve(result) } } }) } catch(rejected){ return this.then(null,rejected) } }測試
new MyPromise((resolve,reject)=>{ console.log(1); //reject(2) resolve(2) console.log(3) setTimeout(()=>{console.log(4)},0) }).then(res=>{ console.log(res) return new MyPromise((resolve,reject)=>{ resolve(5) }).then(res=>{ return res }) }).then(res=>{ console.log(res) }).catch(e=>{ console.log("e",e) }) 執(zhí)行結(jié)果: > 1 > 3 > 2 > 5 > 4
原生promise
new Promise((resolve,reject)=>{ console.log(1); //reject(2) resolve(2) console.log(3) setTimeout(()=>{console.log(4)},0) }).then(res=>{ console.log(res) return new Promise((resolve,reject)=>{ resolve(5) }).then(res=>{ return res }) }).then(res=>{ console.log(res) }).catch(e=>{ console.log("e",e) }) 執(zhí)行結(jié)果: > 1 > 3 > 2 > 5 > 4GitHub
wclimb
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/97698.html
摘要:如果狀態(tài)是等待態(tài)的話,就往回調(diào)函數(shù)中函數(shù),比如如下代碼就會(huì)進(jìn)入等待態(tài)的邏輯以上就是簡單版實(shí)現(xiàn)實(shí)現(xiàn)一個(gè)符合規(guī)范的接下來大部分代碼都是根據(jù)規(guī)范去實(shí)現(xiàn)的。 為更好的理解, 推薦閱讀Promise/A+ 規(guī)范 實(shí)現(xiàn)一個(gè)簡易版 Promise 在完成符合 Promise/A+ 規(guī)范的代碼之前,我們可以先來實(shí)現(xiàn)一個(gè)簡易版 Promise,因?yàn)樵诿嬖囍校绻隳軐?shí)現(xiàn)出一個(gè)簡易版的 Promise ...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識(shí)之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
摘要:的執(zhí)行與狀態(tài)無關(guān)當(dāng)?shù)玫綘顟B(tài)不論成功或失敗后就會(huì)執(zhí)行,原文鏈接參考鏈接對(duì)象 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步與promisejavascript異步之Promise.resolve()、Promise.reject()javascript異步之Promise then和catchjavascript異步之a(chǎn)sync...
摘要:所以增加了異步函數(shù),提高了代碼可讀性,對(duì)不太熟悉的人而言,幫助就更大了。因?yàn)楫惒胶瘮?shù)去掉了所有回調(diào)。這就是此代碼有效的原因它和以下一樣代碼更易讀正如上面示例所見,與回調(diào)和代碼相比,異步函數(shù)代碼看起來非常簡單。 這篇文章詳細(xì)講解了JavaScript中的異步函數(shù)。 JavaScript中的異步代碼在很短的時(shí)間內(nèi)從回調(diào)發(fā)展為Promise,再到ES2017的異步函數(shù),現(xiàn)在我們可以像編寫同步...
摘要:轉(zhuǎn)載自是什么呢根據(jù)的定義是一個(gè)被用于延時(shí)計(jì)算的最終結(jié)果的占位符這個(gè)怎么理解呢比如說,我要去麥當(dāng)勞買點(diǎn)吃的,下單以后人家會(huì)先給你一個(gè)訂單號(hào),等人家外賣做好了,會(huì)提示你,并用那個(gè)訂單小票來換取你真正的食物,在這時(shí)候,那個(gè)訂單小票就是你這頓飯的 轉(zhuǎn)載自: http://www.lht.ren/article/3/ Promise是什么呢?根據(jù)ecma-262的定義: Promise是一個(gè)被用...
閱讀 2270·2023-04-25 14:50
閱讀 1263·2021-10-13 09:50
閱讀 1872·2019-08-30 15:56
閱讀 1847·2019-08-29 15:29
閱讀 2891·2019-08-29 15:27
閱讀 3556·2019-08-29 15:14
閱讀 1201·2019-08-29 13:01
閱讀 3305·2019-08-26 14:06