关于循环promise的解决方案
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 => { //后续操作。。。。。 })
这样循环异步操作的问题就解决了。