ES7的async/await語法在2016年就已經提出來了,慚愧的是我最近才接觸使用,,下面來聊聊express
在async/await以前,咱們有三種方式寫異步代碼npm
嵌套回調promise
以Promise爲主的鏈式回調瀏覽器
使用Generatorsbabel
可是,這三種寫起來都不夠優雅,ES7作了優化改進,async/await應運而生,async/await相比較Promise 對象then 函數的嵌套,與 Generator 執行的繁瑣(須要藉助co才能自動執行,不然得手動調用next() ), Async/Await 可讓你輕鬆寫出同步風格的代碼同時又擁有異步機制,更加簡潔,邏輯更加清晰。異步
async/await更加語義化,async 是「異步」的簡寫,async function 用於申明一個 function 是異步的; await,能夠認爲是async wait的簡寫, 用於等待一個異步方法執行完成;async
async/await是一個用同步思惟解決異步問題的方案(等結果出來以後,代碼纔會繼續往下執行)函數
能夠經過多層 async function 的同步寫法代替傳統的callback嵌套優化
自動將常規函數轉換成Promise,返回值也是一個Promise對象3d
只有async函數內部的異步操做執行完,纔會執行then方法指定的回調函數
異步函數內部可使用await
async function name([param[, param[, ... param]]]) { statements } name: 函數名稱。 param: 要傳遞給函數的參數的名稱 statements: 函數體語句。 返回值: 返回的Promise對象會以async function的返回值進行解析,或者以該函數拋出的異常進行回絕。
await 放置在Promise調用以前,await 強制後面點代碼等待,直到Promise對象resolve,獲得resolve的值做爲await表達式的運算結果
[return_value] = await expression; expression: 一個 Promise 對象或者任何要等待的值。 返回值:返回 Promise 對象的處理結果。若是等待的不是 Promise 對象,則返回該值自己。
在async函數裏,不管是Promise reject的數據仍是邏輯報錯,都會被默默吞掉,因此最好把await放入try{}catch{}中,catch可以捕捉到Promise對象rejected的數據或者拋出的異常
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { try { console.log('start'); await timeout(ms); //這裏返回了錯誤 console.log('end'); //因此這句代碼不會被執行了 } catch(err) { console.log(err); //這裏捕捉到錯誤error } } asyncPrint(1000);
若是不用try/catch的話,也能夠像下面這樣處理錯誤(由於async函數執行後返回一個promise)
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms) console.log('end'); //這句代碼不會被執行了 } asyncPrint(1000).catch(err => { console.log(err); // 從這裏捕捉到錯誤 });
若是你不想讓錯誤中斷後面代碼的執行,能夠提早截留住錯誤,像下面
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => { reject('error') }, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms).catch(err => { // 注意要用catch console.log(err) }) console.log('end'); //這句代碼會被執行 } asyncPrint(1000);
多個await命令的異步操做,若是不存在依賴關係(後面的await不依賴前一個await返回的結果),用Promise.all()讓它們同時觸發
function test1 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(1) }, 1000) }) } function test2 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(2) }, 2000) }) } async function exc1 () { console.log('exc1 start:',Date.now()) let res1 = await test1(); let res2 = await test2(); // 不依賴 res1 的值 console.log('exc1 end:', Date.now()) } async function exc2 () { console.log('exc2 start:',Date.now()) let [res1, res2] = await Promise.all([test1(), test2()]) console.log('exc2 end:', Date.now()) } exc1(); exc2();
exc1 的兩個並列await的寫法,比較耗時,只有test1執行完了纔會執行test2
你能夠在瀏覽器的Console裏嘗試一下,會發現exc2的用Promise.all執行更快一些
在本身的項目中使用
經過 babel 來使用。
只須要設置 presets 爲 stage-3 便可。
安裝依賴:
npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime
修改.babelrc:
"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]
這樣就能夠在項目中使用 async 函數了。
---恢復內容結束---
ES7的async/await語法在2016年就已經提出來了,慚愧的是我最近才接觸使用,,下面來聊聊
在async/await以前,咱們有三種方式寫異步代碼
嵌套回調
以Promise爲主的鏈式回調
使用Generators
可是,這三種寫起來都不夠優雅,ES7作了優化改進,async/await應運而生,async/await相比較Promise 對象then 函數的嵌套,與 Generator 執行的繁瑣(須要藉助co才能自動執行,不然得手動調用next() ), Async/Await 可讓你輕鬆寫出同步風格的代碼同時又擁有異步機制,更加簡潔,邏輯更加清晰。
async/await更加語義化,async 是「異步」的簡寫,async function 用於申明一個 function 是異步的; await,能夠認爲是async wait的簡寫, 用於等待一個異步方法執行完成;
async/await是一個用同步思惟解決異步問題的方案(等結果出來以後,代碼纔會繼續往下執行)
能夠經過多層 async function 的同步寫法代替傳統的callback嵌套
自動將常規函數轉換成Promise,返回值也是一個Promise對象
只有async函數內部的異步操做執行完,纔會執行then方法指定的回調函數
異步函數內部可使用await
async function name([param[, param[, ... param]]]) { statements } name: 函數名稱。 param: 要傳遞給函數的參數的名稱 statements: 函數體語句。 返回值: 返回的Promise對象會以async function的返回值進行解析,或者以該函數拋出的異常進行回絕。
await 放置在Promise調用以前,await 強制後面點代碼等待,直到Promise對象resolve,獲得resolve的值做爲await表達式的運算結果
[return_value] = await expression; expression: 一個 Promise 對象或者任何要等待的值。 返回值:返回 Promise 對象的處理結果。若是等待的不是 Promise 對象,則返回該值自己。
在async函數裏,不管是Promise reject的數據仍是邏輯報錯,都會被默默吞掉,因此最好把await放入try{}catch{}中,catch可以捕捉到Promise對象rejected的數據或者拋出的異常
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { try { console.log('start'); await timeout(ms); //這裏返回了錯誤 console.log('end'); //因此這句代碼不會被執行了 } catch(err) { console.log(err); //這裏捕捉到錯誤error } } asyncPrint(1000);
若是不用try/catch的話,也能夠像下面這樣處理錯誤(由於async函數執行後返回一個promise)
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => {reject('error')}, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms) console.log('end'); //這句代碼不會被執行了 } asyncPrint(1000).catch(err => { console.log(err); // 從這裏捕捉到錯誤 });
若是你不想讓錯誤中斷後面代碼的執行,能夠提早截留住錯誤,像下面
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(() => { reject('error') }, ms); //reject模擬出錯,返回error }); } async function asyncPrint(ms) { console.log('start'); await timeout(ms).catch(err => { // 注意要用catch console.log(err) }) console.log('end'); //這句代碼會被執行 } asyncPrint(1000);
多個await命令的異步操做,若是不存在依賴關係(後面的await不依賴前一個await返回的結果),用Promise.all()讓它們同時觸發
function test1 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(1) }, 1000) }) } function test2 () { return new Promise((resolve, reject) => { setTimeout(() => { resolve(2) }, 2000) }) } async function exc1 () { console.log('exc1 start:',Date.now()) let res1 = await test1(); let res2 = await test2(); // 不依賴 res1 的值 console.log('exc1 end:', Date.now()) } async function exc2 () { console.log('exc2 start:',Date.now()) let [res1, res2] = await Promise.all([test1(), test2()]) console.log('exc2 end:', Date.now()) } exc1(); exc2();
exc1 的兩個並列await的寫法,比較耗時,只有test1執行完了纔會執行test2
你能夠在瀏覽器的Console裏嘗試一下,會發現exc2的用Promise.all執行更快一些
在本身的項目中使用
經過 babel 來使用。
只須要設置 presets 爲 stage-3 便可。
安裝依賴:
npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime
修改.babelrc:
"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]
這樣就能夠在項目中使用 async 函數了。