Wait for for loop to be executed in javascript

I have a for loop that creates products in the database and also want that productsarray to be pushed in another collection ,so I want it to store in a temporary array,but before executing the complete for loop the javascript control goes and executes the rest of the code due to which the temporary array is empty. I want something so that the javascript control goes to next statement only after the for loop is executed completely.

for(let i=0;i<productsname.length;i++){
        name=productsname[i]
        cost=productcost[i]
        Product.create({name:name,cost:cost},function(err,product){
            productArray.push(product);
        })
    }
var newOrder={id:count++,dateofdispatch:req.body.date,transport:req.body.transport,amount:req.body.totalcost,product:productArray}

Upvotes: 0

Views: 72

Answers (5)

Kerem atam
Kerem atam

Reputation: 2797

You should synchronize your code either with Promise or async/await.

Check code below for await example :

(async function () {
  for (let i = 0; i < productsname.length; i++) {
    name = productsname[i];
    cost = productcost[i];
    await Product.create({ name: name, cost: cost }, function (err, product) {
      productArray.push(product);
    });
  }
  var newOrder = await {
    id: count++,
    dateofdispatch: req.body.date,
    transport: req.body.transport,
    amount: req.body.totalcost,
    product: productArray,
  };
  // do another thing and dont forget to use await

})();

await expression can only be used in async function. Above code create an async function and immediately calls it. It is called an IIFE (immediately invoked function expression). You may also create an async function and use somewhere else :

async function createProductArray () {
  for (let i = 0; i < productsname.length; i++) {
    name = productsname[i];
    cost = productcost[i];
    await Product.create({ name: name, cost: cost }, function (err, product) {
      productArray.push(product);
    });
  }
  var newOrder = await {
    id: count++,
    dateofdispatch: req.body.date,
    transport: req.body.transport,
    amount: req.body.totalcost,
    product: productArray,
  };
  // do another thing and dont forget to use await

};

// somewhere in your code
createProductArray()

Upvotes: 0

Marc
Marc

Reputation: 1896

What you can do:

First you can create a promise for Product.create

new Promise(function(resolve, reject) { ... });

then you can create an array with your promises and start all by:

Promise.all(promises).then(res => {  })

See: MDN Promise and MDN Promise.all

Try this:

const promises = [];
for (let i=0; i<productsname.length; i++){
    const name = productsname[i];
    const cost = productcost[i];
    promises.push(
        new Promise((resolve, reject) => {
                Product.create({name,cost},(err,product) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(product);
                    }
                }):
        })
    );
}

Promise.all(promises).then(res => {  
    console.info(res);
    // TODO what you want
});

PS: {name:name,cost:cost} short form: {name,cost}

Upvotes: 1

Fida Khan
Fida Khan

Reputation: 33

if you want to create a temporary Array just do it

const procductArray = [];

your FOR loop

for(let i=0;i<productsname.length;i++){
        const newProduct = {
        name=productsname[i]
        cost=productcost[i]
        }
      Product.create({name:newProduct.name,cost:newProduct.cost},function(err,product){
            productArray.push(newProduct);
        })
    }

Upvotes: 0

Daniele Ricci
Daniele Ricci

Reputation: 15837

You need to use an asynchronous design pattern. Promise.all seems to fit exactly your requirement but I don't know if the library you are using for mongodb is Promise compliant.

If your library is not Promise compliant you can implement them by yourself.

let promiseArray;

for(let i=0;i<productsname.length;i++){
    name=productsname[i]
    cost=productcost[i]
    promiseArray.push(new Promise((resolve,reject) => {
        Product.create({name:name,cost:cost},function(err,product) {
            if(err) reject(err);
            else resolve(product);
        })
    }));
}

Promise.all(promiseArray).then(yourResultArray => {
    // rest of your program goes here
})

Upvotes: 0

Arvind Kalra
Arvind Kalra

Reputation: 99

To handle this you can do something like this:

let numCreated = 0;
for(let i=0;i<productsname.length;i++){
        name=productsname[i]
        cost=productcost[i]
        Product.create({name:name,cost:cost},function(err,product){
            productArray.push(product);
            numCreated++;
            if(numCreated === productsname.length){
              onLoopCompleted(productArray);
            }
        })
    }

function onLoopComplete(productArray){
  var newOrder =  { id: count++, dateofdispatch: req.body.date, transport: req.body.transport, amount: req.body.totalcost, product: productArray }
  // Do what needs to be done here
}

If the library you are using is a promise compliant, then you can look at Promise.all

Upvotes: 0

Related Questions