node.js將回調函數嵌套,用promise改造成async/await順序執行:異常處理和返回多個參數
摘要: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