- Vue.js 3應用開發與核心源碼解析
- 呂鳴
- 1535字
- 2023-08-31 19:30:32
1.5.3 Promise和async/await
1.Promise
Promise是一種適用于異步操作的機制,比傳統的回調函數解決方案更合理和更強大。從語法上說,Promise是一個對象,從它可以獲取異步操作的結果:成功或失敗。在Promise中,有三種狀態:pending(進行中)、resolved(已成功)和rejected(已失敗)。只有異步操作的結果可以決定當前是哪一種狀態,無法被Promise之外的方式改變。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。創建一個Promise對象,代碼如下:
var promise = new Promise(function(resolve, reject) { ... if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } });
在上面的代碼中,創建了一個Promise對象,Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve和reject。這是兩個內置函數,resolve函數的作用是將Promise對象的狀態變為“成功”,在異步操作成功時調用,并將異步操作的結果作為參數傳遞出去;reject函數的作用是將Promise對象的狀態變為“失敗”,在異步操作失敗時調用,并將異步操作報出的錯誤作為參數傳遞出去。當代碼中出現錯誤(Error)時,就會調用catch回調方法,并將錯誤信息作為參數傳遞出去。
Promise對象實例生成后,可以用then方法分別指定resolved(成功)狀態和rejected(失敗)狀態的回調函數以及catch方法,比如:
promise.then(function(value) { // success邏輯 }, function(error) { // failure邏輯 }).catch(function(){ // error邏輯 });
then()方法返回的是一個新的Promise實例(不是原來那個Promise實例)。因此,可以采用鏈式寫法,即then()方法后面再調用另一個then()方法,比如:
getJSON("/1.json").then(function(post) { return getJSON(post.nextUrl); }).then(function (data) { console.log("resolved: ", data); }, function (err){ console.log("rejected: ", err); });
下面是一個用Promise對象實現的Ajax操作get方法的例子。
var getJSON = function(url) { // 返回一個Promise對象 var promise = new Promise(function(resolve, reject){ var client = new XMLHttpRequest(); //創建XMLHttpRequest對象 client.open("GET", url); client.onreadystatechange = onreadystatechange; client.responseType = "json"; //設置返回格式為json client.setRequestHeader("Accept", "application/json");//設置發送格式為json client.send();//發送 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的基本知識可以便于后續學習使用服務端渲染。當然,Promise的應用場合還是比較多的,如果想要深入了解,可以訪問網址:https://developer.mozilla.org/en-US/docs/Web/Java Script/Reference/Global_Objects/Promise,進行系統的學習。
2.async/await
async/await語法在2016年就已經提出來了,屬于ES 7中的一個測試標準(目前來看是直接跳過ES 7,列為ES 8的標準了),它主要為了解決下面兩個問題:
· 過多的嵌套回調問題。
· 以Promise為主的鏈式回調問題。
前面講解過Promise,雖然Promise解決了恐怖的嵌套回調問題,但是解決得并不徹底,過多地使用Promise會引發以then為主的復雜鏈式調用問題,同樣會讓代碼閱讀起來不那么順暢,而async/await就是它們的救星。
async/await是兩個關鍵字,主要用于解決異步問題,其中async關鍵字代表后面的函數中有異步操作,await關鍵字表示等待一個異步方法執行完成。這兩個關鍵字需要結合使用。
當函數中有異步操作時,可以在聲明時在其前面加一個關鍵字async,代碼如下:
async function myFunc() { //異步操作 }
使用async聲明的函數在被調用時會將返回值轉換成一個Promise對象,因此async函數通過return返回的值會進入Promise的resolved狀態,成為then方法中回調函數的參數,代碼如下:
// myFunc()返回一個Promise對象 async function myFunc() { return 'hello'; } // 使用then方法就可以接收到返回值 myFunc().then(value => { console.log(value); // hello })
如果不想使用Promise的方式接收myFunc()的返回值,可以使用await關鍵字更加簡潔地獲取返回值,代碼如下:
async function myFunc() { return 'hello'; } let foo = await myFunc(); // hello
await表示等待一個Promise返回,但是await后面的Promise對象不會總是返回resolved狀態,如果發生異常,則進入rejected狀態,那么整個async異步函數就會中斷執行,為了記錄錯誤的位置和編寫異常邏輯的代碼,需要使用try/catch,代碼如下:
try { let foo = await myFunc(); // hello }catch(e){ // 錯誤邏輯 console.log(e) }
下面舉一個例子,在后面的實戰項目開發中,經常會用到數據接口請求數據,接口請求一般是異步操作,例如在Vue的mounted方法中請求數據,代碼如下:
async mounted () { // 代碼編寫自上而下,一行一行,以便于閱讀 let resp = await ajax.get('weibo/list') let top = resp[0] console.log(top) }
在上面的代碼中,ajax.get()方法會返回一個Promise,采用await進行了接收,并且await必須包含在一個用async聲明的函數中。
可以看出,在使用了async/await之后,整個代碼的邏輯更加清晰,沒有了復雜的回調和煩瑣的換行。
至此,對于實戰項目中用到的相關ES 6語法基本講解完畢,如果讀者想進一步了解ES 6的更多語法知識,可以自行在其官網上學習。
- Moodle Administration Essentials
- JavaScript+jQuery開發實戰
- NativeScript for Angular Mobile Development
- Spring Cloud、Nginx高并發核心編程
- 實戰Java高并發程序設計(第3版)
- Python忍者秘籍
- Fast Data Processing with Spark(Second Edition)
- 寫給程序員的Python教程
- 實戰Java高并發程序設計(第2版)
- 網絡數據采集技術:Java網絡爬蟲實戰
- Visual C++從入門到精通(第2版)
- Learning D3.js 5 Mapping(Second Edition)
- Design Patterns and Best Practices in Java
- HikariCP數據庫連接池實戰
- 青少年Python趣味編程