es6的promise對象解決了js異步回調函數多重嵌套的的噩夢,再也不用寫像這樣的代碼
query('select * from user',function(err,data) { query('select * from user1',function(err,data) { query('select * from user2',function(err,data) { //無窮無盡的異步操作。。。 }) }) })
而可以像這樣。
query('select * from user') .then(function(data) { return query('select * from user1') }) .then(function(data) { return query('select * from user2') }) .then(function(data) { //后續操作。。。 })
代碼的可讀性得到了大大的提升,並且更容易維護。但是promise並不是萬能的,比如說在循環中有多個異步操作,有無窮多個then函數就比較麻煩了,比如這樣
//查詢訂單及每個訂單的每個商品 query('select * from order') .then(data => { var orders = data for(let order of orders) { query('select * from order_prod where oid='+order.oid) .then(data => { order.prods = data }) } //最終需要得到結果 console.log(orders) })
這里需要得到最終的結果就比較令人頭疼了,好在es7的async/await異步方案為我們提供了解決方案。node.js7.6已經原生支持async/await,所以把node更新到7.6以上,就可以放心使用啦。async 可以聲明一個異步函數,此函數需要返回一個 Promise 對象。await 可以等待一個 Promise 對象 resolve,並拿到結果。比如這樣
async function sleep(timeout) { return new Promise((resolve, reject) => { setTimeout(function() { resolve(); }, timeout); }); } (async function() { console.log('Do some thing, ' + new Date()); await sleep(3000); console.log('Do other things, ' + new Date()); })(); //Do some thing, Mon Feb 23 2015 21:52:11 GMT+0800 (CST) //Do other things, Mon Feb 23 2015 21:52:14 GMT+0800 (CST)
所以在循環promise取得最終結果就可以是這樣
let getOrderProd = async data => { var order = data for(let order of orders) { //將之前封裝的基於promised的query函數還原成普通的異步回調模式 await f(order) } //最終需要得到結果 console.log(orders) return new Promise((reslove,reject) => { reslove(orders) }) } function f(i) { return new Promise((resolve,reject) => { query1('select * from order_prod where oid='+order.oid, function(err,data){ i.prods = data resolve(i) }) }) } query('select * from order') .then(getOrderProd).then(data => { //后續操作。。。。。 })
這樣循環異步操作的問題就解決了。