- Vue.js 3應(yīng)用開(kāi)發(fā)與核心源碼解析
- 呂鳴
- 1535字
- 2023-08-31 19:30:32
1.5.3 Promise和async/await
1.Promise
Promise是一種適用于異步操作的機(jī)制,比傳統(tǒng)的回調(diào)函數(shù)解決方案更合理和更強(qiáng)大。從語(yǔ)法上說(shuō),Promise是一個(gè)對(duì)象,從它可以獲取異步操作的結(jié)果:成功或失敗。在Promise中,有三種狀態(tài):pending(進(jìn)行中)、resolved(已成功)和rejected(已失敗)。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),無(wú)法被Promise之外的方式改變。這也是Promise這個(gè)名字的由來(lái),它的英語(yǔ)意思就是“承諾”,表示其他手段無(wú)法改變。創(chuàng)建一個(gè)Promise對(duì)象,代碼如下:
var promise = new Promise(function(resolve, reject) { ... if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } });
在上面的代碼中,創(chuàng)建了一個(gè)Promise對(duì)象,Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject。這是兩個(gè)內(nèi)置函數(shù),resolve函數(shù)的作用是將Promise對(duì)象的狀態(tài)變?yōu)椤俺晒Α保诋惒讲僮鞒晒r(shí)調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞出去;reject函數(shù)的作用是將Promise對(duì)象的狀態(tài)變?yōu)椤笆 保诋惒讲僮魇r(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤作為參數(shù)傳遞出去。當(dāng)代碼中出現(xiàn)錯(cuò)誤(Error)時(shí),就會(huì)調(diào)用catch回調(diào)方法,并將錯(cuò)誤信息作為參數(shù)傳遞出去。
Promise對(duì)象實(shí)例生成后,可以用then方法分別指定resolved(成功)狀態(tài)和rejected(失敗)狀態(tài)的回調(diào)函數(shù)以及catch方法,比如:
promise.then(function(value) { // success邏輯 }, function(error) { // failure邏輯 }).catch(function(){ // error邏輯 });
then()方法返回的是一個(gè)新的Promise實(shí)例(不是原來(lái)那個(gè)Promise實(shí)例)。因此,可以采用鏈?zhǔn)綄?xiě)法,即then()方法后面再調(diào)用另一個(gè)then()方法,比如:
getJSON("/1.json").then(function(post) { return getJSON(post.nextUrl); }).then(function (data) { console.log("resolved: ", data); }, function (err){ console.log("rejected: ", err); });
下面是一個(gè)用Promise對(duì)象實(shí)現(xiàn)的Ajax操作get方法的例子。
var getJSON = function(url) { // 返回一個(gè)Promise對(duì)象 var promise = new Promise(function(resolve, reject){ var client = new XMLHttpRequest(); //創(chuàng)建XMLHttpRequest對(duì)象 client.open("GET", url); client.onreadystatechange = onreadystatechange; client.responseType = "json"; //設(shè)置返回格式為json client.setRequestHeader("Accept", "application/json");//設(shè)置發(fā)送格式為json client.send();//發(fā)送 function onreadystatechange() { if (this.readyState !== 4) { return; } if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; }); return promise; }; getJSON("/data.json").then(function(data) { console.log(data); }, function(error) { console.error(error); });
了解Promise的基本知識(shí)可以便于后續(xù)學(xué)習(xí)使用服務(wù)端渲染。當(dāng)然,Promise的應(yīng)用場(chǎng)合還是比較多的,如果想要深入了解,可以訪問(wèn)網(wǎng)址:https://developer.mozilla.org/en-US/docs/Web/Java Script/Reference/Global_Objects/Promise,進(jìn)行系統(tǒng)的學(xué)習(xí)。
2.a(chǎn)sync/await
async/await語(yǔ)法在2016年就已經(jīng)提出來(lái)了,屬于ES 7中的一個(gè)測(cè)試標(biāo)準(zhǔn)(目前來(lái)看是直接跳過(guò)ES 7,列為ES 8的標(biāo)準(zhǔn)了),它主要為了解決下面兩個(gè)問(wèn)題:
· 過(guò)多的嵌套回調(diào)問(wèn)題。
· 以Promise為主的鏈?zhǔn)交卣{(diào)問(wèn)題。
前面講解過(guò)Promise,雖然Promise解決了恐怖的嵌套回調(diào)問(wèn)題,但是解決得并不徹底,過(guò)多地使用Promise會(huì)引發(fā)以then為主的復(fù)雜鏈?zhǔn)秸{(diào)用問(wèn)題,同樣會(huì)讓代碼閱讀起來(lái)不那么順暢,而async/await就是它們的救星。
async/await是兩個(gè)關(guān)鍵字,主要用于解決異步問(wèn)題,其中async關(guān)鍵字代表后面的函數(shù)中有異步操作,await關(guān)鍵字表示等待一個(gè)異步方法執(zhí)行完成。這兩個(gè)關(guān)鍵字需要結(jié)合使用。
當(dāng)函數(shù)中有異步操作時(shí),可以在聲明時(shí)在其前面加一個(gè)關(guān)鍵字async,代碼如下:
async function myFunc() { //異步操作 }
使用async聲明的函數(shù)在被調(diào)用時(shí)會(huì)將返回值轉(zhuǎn)換成一個(gè)Promise對(duì)象,因此async函數(shù)通過(guò)return返回的值會(huì)進(jìn)入Promise的resolved狀態(tài),成為then方法中回調(diào)函數(shù)的參數(shù),代碼如下:
// myFunc()返回一個(gè)Promise對(duì)象 async function myFunc() { return 'hello'; } // 使用then方法就可以接收到返回值 myFunc().then(value => { console.log(value); // hello })
如果不想使用Promise的方式接收myFunc()的返回值,可以使用await關(guān)鍵字更加簡(jiǎn)潔地獲取返回值,代碼如下:
async function myFunc() { return 'hello'; } let foo = await myFunc(); // hello
await表示等待一個(gè)Promise返回,但是await后面的Promise對(duì)象不會(huì)總是返回resolved狀態(tài),如果發(fā)生異常,則進(jìn)入rejected狀態(tài),那么整個(gè)async異步函數(shù)就會(huì)中斷執(zhí)行,為了記錄錯(cuò)誤的位置和編寫(xiě)異常邏輯的代碼,需要使用try/catch,代碼如下:
try { let foo = await myFunc(); // hello }catch(e){ // 錯(cuò)誤邏輯 console.log(e) }
下面舉一個(gè)例子,在后面的實(shí)戰(zhàn)項(xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)用到數(shù)據(jù)接口請(qǐng)求數(shù)據(jù),接口請(qǐng)求一般是異步操作,例如在Vue的mounted方法中請(qǐng)求數(shù)據(jù),代碼如下:
async mounted () { // 代碼編寫(xiě)自上而下,一行一行,以便于閱讀 let resp = await ajax.get('weibo/list') let top = resp[0] console.log(top) }
在上面的代碼中,ajax.get()方法會(huì)返回一個(gè)Promise,采用await進(jìn)行了接收,并且await必須包含在一個(gè)用async聲明的函數(shù)中。
可以看出,在使用了async/await之后,整個(gè)代碼的邏輯更加清晰,沒(méi)有了復(fù)雜的回調(diào)和煩瑣的換行。
至此,對(duì)于實(shí)戰(zhàn)項(xiàng)目中用到的相關(guān)ES 6語(yǔ)法基本講解完畢,如果讀者想進(jìn)一步了解ES 6的更多語(yǔ)法知識(shí),可以自行在其官網(wǎng)上學(xué)習(xí)。
- C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第三版)
- 小程序?qū)崙?zhàn)視頻課:微信小程序開(kāi)發(fā)全案精講
- Docker進(jìn)階與實(shí)戰(zhàn)
- Java面向?qū)ο筌浖_(kāi)發(fā)
- JavaScript+jQuery網(wǎng)頁(yè)特效設(shè)計(jì)任務(wù)驅(qū)動(dòng)教程(第2版)
- Swift 3 New Features
- Apache Karaf Cookbook
- Mastering RStudio:Develop,Communicate,and Collaborate with R
- C語(yǔ)言程序設(shè)計(jì)
- Haxe Game Development Essentials
- Android玩家必備
- C語(yǔ)言程序設(shè)計(jì)
- Visual Basic 6.0程序設(shè)計(jì)實(shí)驗(yàn)教程
- 深度學(xué)習(xí)入門(mén):基于Python的理論與實(shí)現(xiàn)
- Node.js實(shí)戰(zhàn):分布式系統(tǒng)中的后端服務(wù)開(kāi)發(fā)