摘要:的種狀態(tài)對象一共有進(jìn)行中,已成功和已失敗種狀態(tài)。如果執(zhí)行成功,將返回一個數(shù)組,數(shù)組的值和實(shí)例的返回值一一對應(yīng)。如果返回失敗,會被自己的方法捕獲,經(jīng)過處理后返回一個成功的實(shí)例,返回值是失敗狀態(tài)返回的,最后也就返回成功狀態(tài)。
寫東西真是難啊,一是因?yàn)槎亲永餂]多少貨,二是因?yàn)檎莆盏臇|西也太細(xì)碎表面。好吧,這也是為什么要寫的原因,希望能借此倒逼一下自己。
本來想著一個主題接一個主題的來寫,但是發(fā)現(xiàn)好難。好吧,那就從自己熟悉的東西開始寫。
Promise長啥樣先看大致的代碼
new Promise(function (resolve, reject) { // 執(zhí)行異步操作...... // 判斷異步操作的結(jié)果 if (/* success */) { resolve(value); } else { reject(err); } }).then(res => { // 成功,執(zhí)行后續(xù)操作 }).catch(err => { // 失敗,處理錯誤 })
Promise的字面意思就是承諾,承諾表示表示將要做但是還未做的事情,而且承諾還伴隨著這件事情是成功或者失敗的反饋。所以當(dāng)new一個Promise的時候,就相當(dāng)于告訴js引擎去幫我們執(zhí)行一些操作(同步或者異步的都可以),執(zhí)行完后再告訴我們結(jié)果,然后我們再根據(jù)結(jié)果的成功與否去做之后的操作。
舉個栗子console.log("start...") new Promise(function (resolve, reject) { console.log("start promise...") // 大約0.5秒后執(zhí)行 setTimeout(() => { console.log("start timeout...") // 隨機(jī)生成一個num,1 <= num <= 10 const num = parseInt(Math.random() * 10) + 1 // 大于5算成功,否則算失敗 if (num > 5) { resolve("success") } else { reject("failed") } console.log("end timeout...") }, 500) console.log("end promise...") }).then(res => { console.log(res) }).catch(err => { console.log(err) }) console.log("end...")
運(yùn)行結(jié)果:
start...
start promise...
end promise...
end...
start timeout...
end timeout...
failed/success
這段代碼,首先會打印出start...字符串,然后當(dāng)我們new Promise()的時候,引擎會立刻執(zhí)行Promise里的代碼,所以打印出start promise...。緊接著,遇到setTimeout,所以直接跳到end priomise...處打印該字符串。這個時候,Promise里的代碼暫時執(zhí)行完畢,引擎將切換到Promise外部執(zhí)行后續(xù)的同步代碼,打印出end...。大約在0.5秒后,引擎將切回Primise內(nèi)部執(zhí)行setTimeout的回調(diào)函數(shù),于是打印出start timeout...,但是不管resolve還是reject,只要沒有return語句,都將打印出end promise...,最后才是執(zhí)行then或者catch里的回調(diào)函數(shù)。
Promise的3種狀態(tài)Promise對象一共有pedding(進(jìn)行中),fulfilled(已成功)和rejected(已失敗)3種狀態(tài)。從創(chuàng)建Promise到resolve函數(shù)執(zhí)行之前,都是pedding狀態(tài),resolve()執(zhí)行后變成fulfilled狀態(tài),reject()執(zhí)行后變成rejected狀態(tài)。
Promise的then方法Promise的then方法是在Promise的狀態(tài)改變時調(diào)用,接收兩個參數(shù),第一個參數(shù)是成功時的回調(diào)函數(shù),第二個參數(shù)(可選)是失敗時的回調(diào)函數(shù)。
then方法會返回一個新的Promise實(shí)例,于是我們可以繼續(xù)在then后面寫then(catch方法同樣返回Promise實(shí)例,可以鏈?zhǔn)秸{(diào)用)。這個特性挺有用的,下面用示例說一下。
首先,先創(chuàng)建一個函數(shù),該函數(shù)返回一個Promise實(shí)例,該P(yáng)romise成功或失敗的概率各50%。
const isMoreThanFive = function () { return new Promise(function (resolve, reject) { setTimeout(() => { const num = parseInt(Math.random() * 10) + 1 if (num > 5) { resolve("success") } else { reject("failed") } }, 500) }) }
一個then函數(shù)的情況:
isMoreThanFive() .then((res) => { console.log(res) }) .catch(err => { console.log(err) }) // 0.5秒后輸出success或者failed
兩個then函數(shù)的情況:
isMoreThanFive() .then((res) => { console.log("first " + res); return isMoreThanFive() }) .then(res => { console.log("second " + res); }) .catch(err => { console.log(err) })
這種情況,如果第一個isMoreThanFive執(zhí)行失敗,將直接執(zhí)行catch回調(diào),如果成功,會執(zhí)行第一個then方法,then方法里又通過isMoreThanFive返回了一個新的Promise實(shí)例,這時,如果新的Promise成功將執(zhí)行第二個then方法,如果失敗將執(zhí)行catch方法。
末尾的catch方法會捕獲到前面Promise出現(xiàn)的所有異常,包括reject返回的失敗狀態(tài)和代碼執(zhí)行過程中發(fā)生的錯誤,所以一般會省略then方法的第二個參數(shù)(處理失敗時的回調(diào)),而直接在最后添加catch方法統(tǒng)一處理前面發(fā)生的錯誤。
在調(diào)用接口時,如果B接口依賴A接口返回的參數(shù),這時,then的鏈?zhǔn)秸{(diào)用將非常方便。
先看代碼
const p1 = isMoreThanFive() const p2 = isMoreThanFive() Promise.all([p1, p2]) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) // 輸出 failed 或者 ["success", "success"]
all方法接受一個數(shù)組,數(shù)組各項都是Promise實(shí)例。Promise.all會返回一個新的Promise實(shí)例,只有當(dāng)數(shù)組內(nèi)所有的Promise實(shí)例都成功時,all才返回成功狀態(tài),否則只要有一個失敗都返回失敗狀態(tài)。如果all執(zhí)行成功,將返回一個數(shù)組,數(shù)組的值和Promise實(shí)例的返回值一一對應(yīng)。
注意,傳給all方法的所有Promise實(shí)例都是同時執(zhí)行的,也就是說同時執(zhí)行多個異步操作,如果某個實(shí)例失敗,則all方法直接返回失敗狀態(tài),返回值由失敗的Promise實(shí)例提供。
這在前端渲染頁面時非常有用,利用Promise.all方法將可以同時請求多個接口,提升頁面的渲染速度。
特殊情況,當(dāng)Promise實(shí)例有自己的catch方法時:
const p1 = isMoreThanFive() const p2 = isMoreThanFive() .catch(err => { return err }) Promise.all([p1, p2]) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) // 輸出 failed 或者 ["success", "success"] 或者 [ "success", "failed" ]
如果傳入的Promise實(shí)例有自己的catch方法,就不會觸發(fā)Promise.all的catch方法。p2如果返回失敗,會被自己的catch方法捕獲,經(jīng)過catch處理后返回一個resolved成功的Promise實(shí)例,返回值是失敗狀態(tài)返回的err,最后Promise.all也就返回成功狀態(tài)。
最后多帶帶使用Promise已經(jīng)很方便很直觀了,但是如果配合上async函數(shù)的話,寫異步代碼完全可以使用同步的寫法,下一篇將會寫關(guān)于async的東西。
關(guān)于Promise,大致就是這些,沒有面面俱到,主要是把自己覺得經(jīng)常用到的和重要的寫了下來。如果想了解更多的細(xì)節(jié)和原理可以看阮一峰老師的ES6教程。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98262.html
摘要:的執(zhí)行與狀態(tài)無關(guān)當(dāng)?shù)玫綘顟B(tài)不論成功或失敗后就會執(zhí)行,原文鏈接參考鏈接對象 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步與promisejavascript異步之Promise.resolve()、Promise.reject()javascript異步之Promise then和catchjavascript異步之a(chǎn)sync...
摘要:到這里,我已經(jīng)發(fā)出了一個請求買漢堡,啟動了一次交易。但是做漢堡需要時間,我不能馬上得到這個漢堡,收銀員給我一個收據(jù)來代替漢堡。到這里,收據(jù)就是一個承諾保證我最后能得到漢堡。 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步之Promise.all()、Promise.race()、Promise.finally()javascr...
摘要:所以增加了異步函數(shù),提高了代碼可讀性,對不太熟悉的人而言,幫助就更大了。因?yàn)楫惒胶瘮?shù)去掉了所有回調(diào)。這就是此代碼有效的原因它和以下一樣代碼更易讀正如上面示例所見,與回調(diào)和代碼相比,異步函數(shù)代碼看起來非常簡單。 這篇文章詳細(xì)講解了JavaScript中的異步函數(shù)。 JavaScript中的異步代碼在很短的時間內(nèi)從回調(diào)發(fā)展為Promise,再到ES2017的異步函數(shù),現(xiàn)在我們可以像編寫同步...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
摘要:轉(zhuǎn)載自是什么呢根據(jù)的定義是一個被用于延時計算的最終結(jié)果的占位符這個怎么理解呢比如說,我要去麥當(dāng)勞買點(diǎn)吃的,下單以后人家會先給你一個訂單號,等人家外賣做好了,會提示你,并用那個訂單小票來換取你真正的食物,在這時候,那個訂單小票就是你這頓飯的 轉(zhuǎn)載自: http://www.lht.ren/article/3/ Promise是什么呢?根據(jù)ecma-262的定義: Promise是一個被用...
閱讀 2258·2021-11-23 09:51
閱讀 1091·2021-11-22 15:35
閱讀 4893·2021-11-22 09:34
閱讀 1626·2021-10-08 10:13
閱讀 3029·2021-07-22 17:35
閱讀 2561·2019-08-30 15:56
閱讀 3093·2019-08-29 18:44
閱讀 3110·2019-08-29 15:32