Promise是如何實現非同步程式設計的?

2022-01-20 01:08:35 字數 4528 閱讀 2309

不能免俗地貼個promise標準鏈結promises/a+。es6的promise有很多方法,包括promise.all()/promise.resolve()/promise.reject()等,但其實這些都是promises/a+規範之外的,promises/a+規範只定義了乙個promise.then()方法,這是promise的核心。

new promise((resolve, reject) =>  else 

}).then(res => , err => )

promise接收乙個函式作為引數,我們稱之為executor,該函式有兩個引數resolve和reject,這兩個引數也都是函式,並且,它們定義在promise內部。

那麼我們定義乙個class並定義乙個_isfunction方法,用來校驗建構函式的引數必須是函式。再定義resolve和reject這兩個方法。

class mypromise is not a function`);

}} _isfunction(val)

_resolve()

_reject()

}

promise有三種狀態,分別是pending(等待中)、fulfilled(成功)、rejected(失敗)。狀態改變只能從pending => fulfilled,或者pending => rejected。

resolve的作用,就是將promise的狀態從pending改為fulfilled,它接收乙個引數作為promise執行成功的值,這個值會傳給then的第乙個**函式。reject的作用是將promise的狀態從pending改為rejected,它也接收乙個引數作為promise執行失敗的值,這個值會傳給then的第二個**函式。

那麼我們定義好狀態_status、_resolve、_reject,再定義兩個陣列_handlefulfilled、_handlerejected,分別存放then的成功和失敗**集合。當使用者呼叫resolve或reject方法後,開始非同步呼叫_handlefulfilled或_handlerejected陣列中的**。

class mypromise  is not a function`);

}this._status = "pending";

this._value = undefined;

this._handlefulfilled = ;

this._handlerejected = ;

// 很多文章在這裡給executor加了try catch,實際上原生promise的executor中的錯誤並沒有捕獲

executor(this._resolve.bind(this), this._reject.bind(this));

} _isfunction(val)

_resolve(value)

}, 0)

}} _reject(value)

}, 0);

}}}

promise.then定義了兩個**onfulfilled和onrejected

promise.then(onfulfilled, onrejected)
它們分別在promise執行成功/失敗時執行,它們都是可選的,promises/a+規範規定,如果onfulfilled或onrejected不是函式,將被忽略,promise會繼續執行下乙個then的**。比如下面的例子會輸出1,.then(2)則被忽略了。

new promise((resolve, reject) => )

.then(2)

.then((res) => );

then可以鏈式呼叫,是因為每個then都會返回乙個新的promise。為什麼要返回新的promise?因為每個then都可以返回不同的值,如果用同乙個promise,狀態變化後是不能再修改的,無法做到返回不同的值。

then的**執行onfulfilled還是onrejected,取決於promise的狀態,如果promise狀態為pending,只會將onfulfilled和onrejected分別push到_handlefulfilled和_handlerejected陣列;如果狀態為fulfilled,會執行對應的onfulfilled;如果狀態是rejected,執行對應的onrejected;

那麼then方法的基本結構如下

then(onfulfilled, onrejected)  = this;

// 如果onfulfilled、onrejected不是函式,強制改為函式,並且該函式直接返回接收到的引數,傳後面的then的**函式

onfulfilled = self._isfunction(onfulfilled) ? onfulfilled : (v) => v;

onrejected = self._isfunction(onrejected) ? onrejected : (v) => v;

return new mypromise((resolve, reject) =>

});}

在then鏈式呼叫的情況下,如果前乙個then返回的是乙個新promise,後乙個then的**必須等這個新promise的狀態改變後才會執行。舉例,下面的**輸出1之後,等待3秒才會輸出2:

new promise(resolve => ).then(() => , 3000)

})}).then(() => )

因此要對then的**函式的返回值做個判斷,如果返回值不是promise,利用resolve直接返回這個值;如果返回值是promise,就要等這個promise狀態變化之後再返回,而promise狀態變化之後一定會呼叫then的**函式,利用這個特性,將resolve、reject作為then的**函式即可。

then(onfulfilled, onrejected)  = this;

// 如果onfulfilled、onrejected不是函式,強制改為函式,並且該函式直接返回接收到的引數,傳後面的then的**函式

onfulfilled = self._isfunction(onfulfilled) ? onfulfilled : (v) => v;

onrejected = self._isfunction(onrejected) ? onrejected : (v) => v;

return new mypromise((resolve, reject) => else

};const rejected = (value) => else

};switch (_status)

});}

完整**

class mypromise  is not a function`);

}this._status = "pending";

this._value = undefined;

this._handlefulfilled = ;

this._handlerejected = ;

// 很多文章在這裡給executor加了try catch,實際上原生promise的executor中的錯誤並沒有捕獲

executor(this._resolve.bind(this), this._reject.bind(this));

} _isfunction(val)

_resolve(value)

}, 0);

}} _reject(value)

}, 0);

}} then(onfulfilled, onrejected) = this;

// 如果onfulfilled、onrejected不是函式,強制改為函式,並且該函式直接返回接收到的引數,傳後面的then的**函式

onfulfilled = self._isfunction(onfulfilled) ? onfulfilled : (v) => v;

onrejected = self._isfunction(onrejected) ? onrejected : (v) => v;

return new mypromise((resolve, reject) => else

};const rejected = (value) => else

};switch (_status)

});}}

測試一下,先輸出1,3秒後輸出2,說明mypromise的基本功能沒問題了。

new mypromise((resolve) => , 3000)

}).then(res => )

最後,總結一下,promise是如何實現非同步程式設計的?

promise接收乙個函式為引數,傳入了兩個內部的方法resolve和reject,然後用then註冊**函式,手動呼叫resolve或reject就可以依次執行then的**,並且給**函式傳值。如果then返回的也是promise,同樣的,手動呼叫resolve或reject後,才會繼續往下執行。

其實本質上還是**函式,只不過寫法變了。

使用promise實現非同步

作為乙個新的es6非同步程式設計的解決方案,promise想必大家都聽說過,包括async await 也是基於promise的,今天我們通過乙個小例子來全域性了解一下promise 在此之前,需要明白的是,promise實際上就是乙個包含非同步操作的容器,有三種狀態。pending 進行中 ful...

簡單實現非同步程式設計promise模式

非同步程式設計 j ascript非同步程式設計,web2.0時代比較熱門的程式設計方式,我們平時碼的時候也或多或少用到,最典型的就是非同步ajax,傳送非同步請求,繫結 函式,請求響應之後呼叫指定的 函式,沒有阻塞其他 的執行。還有像settimeout方法同樣也是非同步執行 的方法。如果對非同步...

非同步解決方案promise及原始碼實現

js語言的特性,造就了特別的非同步處理方式,我記得以前用的最多的就是 函式,那個時候寫jquery的ajax時候,特別喜歡寫這種 ajax 後乙個ajax的傳送需要依賴前面的ajax的返回,也許有的朋友說還好啊,其實一兩個確實還好,但是多了就比較暈。不直觀。後面除錯起來有點麻煩。後來很多瀏覽器就自己...