本篇文章通過多段代碼實例帶大家了解 Promise 的基礎(chǔ)用法,以及更進一步掌握 Promise 異步存取的思想。
之前一直有聽說 Promise 的威名,但是總覺得是個較為深奧的東西,有點畏難而沒能真正地去了解。最近看了李立超老師在B站傳的 Node.js 的視頻,感覺講的很清晰,自己在這做進一步的梳理。
(資料圖片)
我們都知道 JavaScript 是單線程運行的,所以如果遇到一個數(shù)據(jù)需要過段時間才能獲取到的情況,就會形成阻塞導(dǎo)致后面的代碼也無法執(zhí)行,而這相當致命,比如下面代碼
function sum(a, b) { const begin = Date.now(); while(Date.now() - begin < 10000) { } return a+b;}console.log(sum(1,2));console.log("1");中間的 while 語句經(jīng)歷了10秒的循環(huán),最終才分別打印出了 3 和 1
然而我們希望的是允許3在10秒后再打印出來,但是1得先打印出來
這里我們就用到了setTimeout,修改代碼如下
function sum(a, b) { setTimeout(() => { return a+b; },10000)}console.log(sum(1,2));console.log("1");運行一下可以看到1確實瞬間被打印出來了,但是本該打印3的位置是undefined
原因在于此時的console.log同樣沒有等待setTimeout走完,無法接收到10秒后的數(shù)據(jù)
所以為了能夠接收到這個10秒后的數(shù)據(jù),我們可以采用回調(diào)函數(shù)的方式
function sum(a, b, callback) { setTimeout(() =>{ callback(a+b); }, 10000)}sum(1,2,(result) => { console.log(result);});console.log("1");傳入了一個能夠接收 a+b 為參數(shù)的回調(diào)函數(shù) (result) => {console.log(result);}
所以在10秒后會執(zhí)行這個回調(diào)函數(shù),進行打印,結(jié)果如下
這樣我們就初步解決了這個問題,一個需要延時獲取的數(shù)據(jù)在其他代碼先執(zhí)行后再被獲取。
然而 Promise 還沒出現(xiàn),這就涉及了另一個需要改進的地方
這是個乍一聽很唬人的稱呼,實際上就是多層回調(diào)函數(shù)的嵌套導(dǎo)致的不利于閱讀和調(diào)試的情況。
比如此時我們想要多次調(diào)用這個sum函數(shù),要在得到1+2的結(jié)果后,再獲得 1+2+3,1+2+3+4 這些結(jié)果
所以我們得在sum傳入的回調(diào)函數(shù)里再多次調(diào)用sum進行嵌套,如下
sum(1,2,(result) => { sum(result, 3, (result) => { sum(result, 4, (result) => { console.log(result); }) })});這種類似金字塔的結(jié)構(gòu)可讀性差且不好調(diào)試,被稱作回調(diào)地獄。
所以此時終于到了Promise出場的時候,它的出現(xiàn)解決了回調(diào)地獄的問題。
在使用Promise解決回調(diào)地獄的問題前,先來大致地了解一下什么是Promise。
目前我對它的判斷是,Promise 是一個用于存取異步數(shù)據(jù)的對象。
首先來看一下空的 Promise 打印出來會是什么
const promise = new Promise(()=>{});其中最關(guān)鍵的就是 PromiseState 和 PromiseResult 兩個值,之后會詳細展開,這里只要知道Promise中有著這兩個屬性即可。
接著來看一下 promise 存數(shù)據(jù)的過程,最關(guān)鍵的就是要知道有 resolve 和 reject,比如下面代碼
const promise = new Promise((resolve, reject) => { const flag = true; if (flag) { resolve("resolve datas"); } else { reject("reject data"); }})此時flag為true,所以執(zhí)行的是resolve的存儲,得到的結(jié)果如下
而當我們把flag改為false,執(zhí)行reject的存儲時,得到的結(jié)果如下
現(xiàn)在是解釋上面兩個屬性的時候了,
當 promise 沒有存儲數(shù)據(jù)時,PromiseState 的值為 pending,PromiseResult的值為 undefined當 promise 使用 resolve 存儲數(shù)據(jù)時,PromiseState 的值為 pending,PromiseResult的值為 相應(yīng)存儲值當 promise 使用 reject 存儲數(shù)據(jù)時,PromiseState 的值為 rejected,PromiseResult的值為相應(yīng)存儲值既然存有兩種類型,讀自然也要分兩種
當我們讀取promise中的數(shù)據(jù)時,我們需要使用如下的結(jié)構(gòu)
promise.then(result => { console.log(result);}, reason => { console.log(reason);})如果數(shù)據(jù)存在resolve中,result會返回結(jié)果,如果存在reject中,reason會返回結(jié)果。
在初步了解了Promise后,會發(fā)現(xiàn)目前Promise能做的事,使用回調(diào)函數(shù)也能完成。
所以最主要的還是Promise解決了回調(diào)地獄,比如之前的問題,可以寫成這種形式
function sum(a, b) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(a+b); }, 1000); })}sum(1,2) .then(result => sum(result,3)) .then(result => sum(result,4)) .then(result => { console.log(result); })promise 通過then方法進行讀取后,是個新的Promise對象,比如我們可以打印一下
function sum(a, b) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(a+b); }, 1000); })}console.log(sum(1,2) .then(result => sum(result,3)))所以這也就給了我們能多次調(diào)用then方法的基礎(chǔ)。
而這也就解決了回調(diào)地獄的問題。
Promise 是一個可以存取異步數(shù)據(jù)的對象,通過resolve和reject來存儲數(shù)據(jù),可以通過then來讀取數(shù)據(jù)
至于其他的.catch.finally.race.any.all這些方法就不再多作贅述,詳細的見文檔
【推薦學(xué)習(xí):javascript高級教程】
以上就是通過代碼實例帶你了解Promise的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
關(guān)鍵詞: JavaScript Node.js