JS中Promise函數(shù)then的奧秘探究
Promise概述
Promise對象是CommonJS工作組提出的一種規(guī)范,目的是為異步操作提供統(tǒng)一接口。
那么,什么是Promises?
首先,它是一個對象,也就是說與其他JavaScript對象的用法,沒有什么兩樣;其次,它起到代理作用(proxy),充當異步操作與回調(diào)函數(shù)之間的中介。它使得異步操作具備同步操作的接口,使得程序具備正常的同步運行的流程,回調(diào)函數(shù)不必再一層層嵌套。
簡單說,它的思想是,每一個異步任務立刻返回一個Promise對象,由于是立刻返回,所以可以采用同步操作的流程。這個Promises對象有一個then方法,允許指定回調(diào)函數(shù),在異步任務完成后調(diào)用。
Promise的then方法可以接受前一個函數(shù)的執(zhí)行結果,還可以保證另一個Promise的順序執(zhí)行,這到底是怎么做到的呢?
原理圖(先上圖)
問題需求
如何保證多個 promise 順序執(zhí)行?
實例:
var f1 = function (){ return new Promise(function (resolve, reject){ setTimeout(function (){ console.log("f1 ok!") resolve("f1 ok!"); }, 1000) }); } var f2 = function (){ return new Promise(function (resolve, reject){ setTimeout(function (){ console.log("f2 ok!") resolve("f2 ok!"); }, 3000) }); } var f3 = function (){ return new Promise(function (resolve, reject){ setTimeout(function (){ console.log("f3 ok!") resolve("f3 ok!"); }, 2000) }); }
當然如果要并行的話,我們很容易想到 Promise.all 方法:
Promise.all([f1(), f2(), f3()]).then(function (data){ console.log(data) }) // f1 ok! // f3 ok! // f2 ok! // ["f1 ok!", "f2 ok!", "f3 ok!"]
如果要順序執(zhí)行:
f1().then(f2).then(f3) // f1 ok! // f2 ok! // f3 ok! //或者這樣 function f(all) { var promise = Promise.resolve(); all.forEach((p, index) => { promise = promise.then(p) }) } f([f1, f2, f3])
那么問題來了,then是如何做到順序執(zhí)行的呢,參數(shù)既可以是一個普通函數(shù),也可是是一個返回promise的函數(shù)?
then的奧秘
很多實現(xiàn)promise的庫都比較復雜,如果自己實現(xiàn)的話,可以借鑒下面簡單的代碼:
Promise.prototype.then = function(onFulfilled, onRejected) { var promise = this; return new Promise(function(resolve, reject) { function handle(value) { var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value; if (ret && typeof ret['then'] == 'function') { ret.then(function(value) { resolve(value); }, function(reason) { reject(reason); }); } else { resolve(ret); } } function errback(reason) { reason = typeof onRejected === 'function' && onRejected(reason) || reason; reject(reason); } if (promise._status === 'PENDING') { promise._resolves.push(handle); promise._rejects.push(errback); } else if (promise._status === FULFILLED) { callback(promise._value); } else if (promise._status === REJECTED) { errback(promise._reason); } }); }
重點在then的實現(xiàn),看上述代碼,每個then返回的是什么,是一個新的 Promise,一個新的 Promise,一個新的 Promise
第二個重點是,在內(nèi)部又處理了一個 回調(diào)函數(shù)運行結果是 一個 promise的 判斷,如果是那么等待這個promise運行結束才調(diào)用 resolve 更改狀態(tài),關鍵是resolve的調(diào)用時機,resolve的調(diào)用時機,才能夠往下執(zhí)行,這兩步就是then函數(shù)的關鍵。
是不是 有點暈,請看最開始的圖。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
javascript連接mysql與php通過odbc連接任意數(shù)據(jù)庫的實例
下面小編就為大家分享一篇javascript連接mysql與php通過odbc連接任意數(shù)據(jù)庫的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12HTML中setCapture、releaseCapture 使用方法淺析
本文給大家簡單介紹了下html中的高級拖動技術setCapture、releaseCapture的使用方法,有需要的小伙伴可以參考下2016-09-09JS實現(xiàn)點擊下拉菜單把選擇的內(nèi)容同步到input輸入框內(nèi)的實例
下面小編就為大家分享一篇JS實現(xiàn)點擊下拉菜單把選擇的內(nèi)容同步到input輸入框內(nèi)的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01