這篇文章主要介紹JavaScript基礎(chǔ)教程之怎么實(shí)現(xiàn)一個(gè)簡單的promise,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

前言
我們?cè)陂_發(fā)過程中大多會(huì)用到promise,想必大家對(duì)promise的使用都很熟練了,今天我們就來實(shí)現(xiàn)一個(gè)簡單的promise,實(shí)現(xiàn)的效果如有出入還往指正。
Promise/A+規(guī)范:
首先重新閱讀了下A+的規(guī)范:
promise代表了一個(gè)異步操作的最終結(jié)果,主要是通過then方法來注冊(cè)成功以及失敗的情況,
Promise/A+歷史上說是實(shí)現(xiàn)了Promise/A的行為并且考慮了一些不足之處,他并不關(guān)心如何創(chuàng)建,完成,拒絕Promise,只考慮提供一個(gè)可協(xié)作的then方法。
術(shù)語:
promise是一個(gè)擁有符合上面的特征的then方法的對(duì)象或者方法。
thenable是定義了then方法的對(duì)象或者方法
value是任何合法的js的值(包括undefined,thenable或者promise)
exception是一個(gè)被throw申明拋出的值
reason是一個(gè)指明了為什么promise被拒絕
整體結(jié)構(gòu)
我們先來梳理一下整體的結(jié)果,以便后續(xù)好操作
class MyPromise {
constructor(fn){
}
resolve(){
}
then(){
}
reject(){
}
catch(){
}
}Promise理論知識(shí)
摘抄至 http://es6.ruanyifeng.com/#docs/promise#Promise-all
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
resolve
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)前的值為接收的值
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
}
reject(reason){
if(this.state !== 'pending') return;
this.state = 'rejected';
this.value = reason
}
}當(dāng)reject執(zhí)行,接收到一個(gè)值之后;狀態(tài)就由 pending -> rejected;當(dāng)前的值為接收的值
then
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)
}
}
})
}
}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é)果
catch
class 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)
}
}測(cè)試
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
> 4
以上是“JavaScript基礎(chǔ)教程之怎么實(shí)現(xiàn)一個(gè)簡單的promise”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)頁題目:JavaScript基礎(chǔ)教程之怎么實(shí)現(xiàn)一個(gè)簡單的promise-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://chinadenli.net/article20/digeco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站制作、外貿(mào)建站、微信小程序、定制開發(fā)、動(dòng)態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容