简体   繁体   中英

Async node.js :nested array with callback

I have an array like this

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

what i want is loop through this array and do database insert for items array

eg without async

products.forEach((pdct) =>{

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

});

I want the same to achive with async and get result after all items inserted

which one i need to use each or eachSeries method i am confusing with it

The difference between each and eachSeries is that the eachSeries runs a single async operation at a time. So for each there is no guarantee that the iteratee functions will complete in order.

So if you don't need an order like in iteratee better to use each , otherwise use eachSeries

Examples:

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()
})

It can return

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

eachSeries:

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()
})

It will return

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

You don't have to use external libraries to performance a synchronous for loop in JavaScript, you just have to use the async/await syntax to do that

Take a look at this code that insert one by one your records waiting for each one to finish until jump to the next one.

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)
}) 

If you promisify that callback, you can do this pretty simply with Promise.all , which wraps an array of Promises and resolves once each Promise in the array resolves.

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']]
})

If you are using Node 8 you could also get rid of the .then and use the await keyword instead:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM