摘要:var step = function(isError, cb) { setTimeout(function() { console.log(new Date()) cb && cb(isError && new Error('step Error'), [ isError, Date.now() ]) }, 1000) } var stepAsync = util.promisify(step) var test = async function() { try { let [ result1, time1 ] = await stepAsync(0) let [ result2, time2 ] = await stepAsync(0) console.log(result1, time1, result2, time2) } catch(e) { console.log(e) } } test()。在ES6語法出現之前,如果想要若干個異步過程按順序執行,則需要使用回調嵌套,比如這裏有個step函數,執行需要一定的時間:。

回調嵌套

在ES6語法出現之前,如果想要若干個異步過程按順序執行,則需要使用回調嵌套,比如這裏有個step函數,執行需要一定的時間:

var step = function(isError, cb) {
 setTimeout(function() {
   console.log(new Date())
   cb && cb(isError && new Error('step Error'), isError)
 }, 1000)
}

如果想要執行兩次step,並且必須按順序個條一條執行,在以前一般要使用回調嵌套:

var test = function() {
 step(0, function(err, isError1) {
   if (err) {
     console.log(err)
   }

   step(0, function(err, isError2) {
     if (err) {
       console.log(err)
     }

   })
 })
}

用async/await

在ES6語法中,可以通過async/await將上面的回調函數按順序執行。

首先將原來的方法 promisify 化,引用 util 庫將 step 函數即可:

const util = require('util')

var stepAsync = util.promisify(step)

然後用 async/await 順序執行,注意 await 只能在 async 函數中使用

var test = async function() {
 let result1 = await stepAsync(0)
 let result2 = await stepAsync(0)
 console.log(result1, result2)
}

test()

結果:

2020-02-18T07:54:01.081Z
2020-02-18T07:54:01.081Z
0 0

其實 util.promisify 只是將函數封裝成了Promise對象,實現並不複雜,不過使用promisify有兩個前提條件

1. Error first 原則: 即你在調用回調函數時,第一個必須爲error

2. Callback last 原則: 即在往函數傳參數時,最後一個參數是回調函數

異常處理

在 async/await 中使用 try/ catch 捕獲處理異常

var test = async function() {
 try {
   let result1 = await stepAsync(0)
   let result2 = await stepAsync(1)
   console.log(result1, result2)
 } catch(e) {
   console.log(e)
 }
}

test()

結果:

2020-02-18T07:54:01.081Z
2020-02-18T07:54:01.081Z
Error: step Error
 at Timeout._onTimeout (testAwait.js:59:25)
 at ontimeout (timers.js:475:11)
 at tryOnTimeout (timers.js:310:5)
 at Timer.listOnTimeout (timers.js:270:5)

多參數返回

估計大家已經看到了,類似這樣的調用,只能接收一個參數:

 let result1 = await stepAsync(0)

目前在JavaScript還沒有一種語法可以在一行語法中同時給兩個變量分別賦值,期待在以後的JS版本里有所改進。所以如果你的方法中要返回一個以上的參數,可以將其變成成數組或對象:

比如,下面是使用數組返回的例子:

 
var step = function(isError, cb) {
 setTimeout(function() {
 console.log(new Date())
 cb && cb(isError && new Error('step Error'), [ isError, Date.now() ])
 }, 1000)
}

var stepAsync = util.promisify(step)

var test = async function() {
 try {
 let [ result1, time1 ] = await stepAsync(0)
 let [ result2, time2 ] = await stepAsync(0)
 console.log(result1, time1, result2, time2)
 } catch(e) {
 console.log(e)
 }
}

test()

執行:

$ node testAwait.js
2020-02-18T08:10:31.328Z
2020-02-18T08:10:32.365Z
0 1582013431334 0 1582013432365
相關文章