【问题标题】:Async node.js :nested array with callback异步 node.js:带有回调的嵌套数组
【发布时间】:2018-06-27 07:40:03
【问题描述】:

我有一个这样的数组

var products = [
            {'id':1 ,items:['a','b']},
            {'id':2,items:['c','d']}
           ]

我想要的是遍历这个数组并为items数组插入数据库

例如没有异步

products.forEach((pdct) =>{

    pdct.items.forEach((item) => {
           calltoDb(item,function(result){
               console.log(item+'item inserted');
             })       
       });

});

我希望async 也能达到同样的效果,并在插入所有项目后得到结果

我需要使用哪个eacheachSeries 方法我对此感到困惑

【问题讨论】:

  • 你需要并行运行calltodb还是一个接一个?
  • @zabusa calltodb 一一不并行
  • 您可以使用await Promise.all 以干净的方式实现此目的,而无需使用 caolan 异步模块。

标签: javascript arrays node.js express asynchronous


【解决方案1】:

如果您承诺该回调,您可以使用Promise.all 非常简单地做到这一点,它包装了一个 Promise 数组,并在数组中的每个 Promise 解析后解析。

Promise.all(products.map(product => {
    return Promise.all(product.items.map(item => {
        return new Promise(resolve => {
            calltoDb(item, resolve)
        })
    }))
})).then(results => {
    console.log(results)  // item results are in a nested array:
                          //     [['a','b'],
                          //      ['c', 'd']]
})

如果您使用的是 Node 8,您也可以去掉 .then 并改用 await 关键字:

const results = await Promise.all(products.map(product => {
    return Promise.all(product.items.map(item => {
        return new Promise(resolve => {
            calltoDb(item, resolve)
        })
    }))
}))

【讨论】:

    【解决方案2】:

    您不必使用外部库在 JavaScript 中执行同步 for 循环,只需使用 async/await 语法即可

    看看这段代码,它会一一插入你的记录,等待每一个完成,直到跳转到下一个。

    async function insert() {
        var all_results = []
        for (var pdct of products) {
            for (var item of pdct.items) {
                var result = await new Promise(next => {
                    calltoDb(item, res => next(res))
                })
                all_results.push(result)
            }
        }
        return all_results
    }
    
    insert().then(results => {
        console.log('Here u have all results', results)
    }) 
    

    【讨论】:

      【解决方案3】:

      eacheachSeries 之间的区别在于 eachSeries 一次运行一个异步操作。所以对于each,不能保证迭代函数会按顺序完成。

      所以如果你不需要像 iteratee 这样的订单最好使用each,否则使用eachSeries

      例子:

      import each from 'async/each'
      let products = [
         {'id':1 ,items:['a','b']}
         , {'id':2, items:['c','d']}
         , {'id':3, items:['e','f']}
      ]
      each(products, (product, callback) => {
         console.log(product)
         return callback()
      })
      

      可以返回

      {'id':3, items:['e','f']}
      {'id':1 ,items:['a','b']}
      {'id':2, items:['c','d']}
      

      每个系列:

      import eachSeries from 'async/eachSeries'
      let products = [
         {'id':1 ,items:['a','b']}
         , {'id':2, items:['c','d']}
         , {'id':3, items:['e','f']}
      ]
      eachSeries(products, (product, callback) => {
         console.log(product)
         return callback()
      })
      

      它会返回

      {'id':1 ,items:['a','b']}
      {'id':2, items:['c','d']}
      {'id':3, items:['e','f']}
      

      【讨论】:

      • 你能举一个当前场景的例子
      • @iambatman 我也更新了我的示例。但它会像我之前展示的那样以相同的方式工作。 eachSeries 将按照您在数组中提供的顺序循环数组。每个不保证与数组中的顺序相同。
      猜你喜欢
      • 2012-07-15
      • 2018-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      相关资源
      最近更新 更多