简体   繁体   English

for 循环中的承诺

[英]promises inside for loop

ignore the syntax error.i need to do perform some thing with i value inside aggregate and need to update it,but when i execute the below code, the for loop is not waiting to finish till update.it iterate i value very fast and the aggregate skips every i value.忽略语法错误。我需要对聚合中的 i 值执行一些操作并需要更新它,但是当我执行下面的代码时,for 循环不会等待完成直到更新。它迭代 i 值非常快并且聚合跳过每个 i 值。 am new to javascript so,incase if the question is silly sorry for that too我是 javascript 的新手,所以,如果这个问题也很愚蠢,我很抱歉

model.countDocuments((err,count)=>{    
for(i=value;i<count;i++){
     console.log(i)
     model.aggregate({[//some update function]})
     .then((res)=>model.update({field:something},{$set:res.value}}))
})

Try using async/await functionality尝试使用异步/等待功能

Change your code to this将您的代码更改为此

model.countDocuments(async (err,count)=>{    
    for(i=value;i<count;i++){
         console.log(i);
         let res = await model.aggregate({[/*some update function]*/});
         model.update({field:something},{$set:res.value}});
    }
)

Using the await keyword will make the code wait until the promise is returned and continue on the next statement.使用 await 关键字将使代码等待,直到返回 promise 并继续下一条语句。

To use the 'await' keyword, the enclosing function needs to declare itself as an 'async' function要使用“await”关键字,封闭的 function 需要将自己声明为“async” function

You can use Promise.all to still have most of your work done concurrently, and still have your results when they are all done running, in the same order you started them.您可以使用Promise.all来同时完成大部分工作,并且在所有工作完成后仍然可以让您的结果按照您启动它们的顺序运行。 Here's a fully working example that somewhat resembles your problem.这是一个与您的问题有些相似的完整工作示例。

// Generate a random value between 250 and 500. Used for the delay to setTimeout 
// to mimic "long running" operations.
const delay = () => Math.floor(Math.random()*(500 - 250 + 1))+250;

// This represents your model.aggregate function. Takes an input of a number for
// the sake of correlation in this example. Always resolves a string with the
// intention of passing it into the next "then."
const aggregate = (i) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => { resolve(`[${i}]: aggregated`) }, delay());
  });
};

// This represents your model.update function. Takes a number for the sake of
// correlation and the result from the "aggregate" function.
const update = (i, res) => {
  // result from aggregate
  console.log(`[${i}]: ${res}`);

  return new Promise((resolve, reject) => {
    setTimeout(() => { resolve(`[${i}]: updated`) }, delay());
  });
};

// A helper to generate an array of numbers. Just a "fancier" alternative to
// "for i=value; i<count; i++"
const range = (i) => [...Array(i).keys()]

// An arbitrary number for the amount of work to run in this example. This 
// represents "count" in your example.
const count = 10;

// This is the equivalent of what would be your for loop's body. Executes "count"
// amount of work and stores all the the promises into an array. Even though we
// have a list of promises in the array, this is non-blocking and the program will
// continue until we wait for them to all resolve later.
const res = range(count).map((i) => {
  console.log(`[${i}]: starting`);
  return aggregate(i).then((res) => update(i, res));
});

// Wait for all promises to resolve and print the final results. At this
// exact moment, some be still running and some may have completed.
// Call then will let you get the results of all the work when they are
// are all resolved.
//
// The block in "catch" will be called when any one of them "rejects" or
// throws an exception.
Promise.all(res).
  then((vals) => { for (const val of vals) { console.log(val) } }).
  catch((err) => { console.error(err) });

Here's an example output:这是一个示例 output:

[0]: starting
[1]: starting
[2]: starting
[3]: starting
[4]: starting
[5]: starting
[6]: starting
[7]: starting
[8]: starting
[9]: starting
[6]: [6]: aggregated
[2]: [2]: aggregated
[4]: [4]: aggregated
[7]: [7]: aggregated
[9]: [9]: aggregated
[3]: [3]: aggregated
[0]: [0]: aggregated
[1]: [1]: aggregated
[8]: [8]: aggregated
[5]: [5]: aggregated
[0]: updated
[1]: updated
[2]: updated
[3]: updated
[4]: updated
[5]: updated
[6]: updated
[7]: updated
[8]: updated
[9]: updated

Notice that the final outputs are in the same order as how they are started (0 through 9).请注意,最终输出的顺序与它们的开始顺序相同(0 到 9)。 However, the "aggregate" and "update" are still run asynchronously.但是,“聚合”和“更新”仍然异步运行。

The point of this is that you don't need to wait for the first "aggregate then update" call to finish to run the next "aggregate then update," then the next "aggregate then update" after that and so on.这样做的重点是,您不需要等待第一个“聚合然后更新”调用完成以运行下一个“聚合然后更新”,然后再运行下一个“聚合然后更新”,依此类推。 Pretty much throwing "asynchronicity" out the window.几乎将“异步”扔出 window。 Using async/await definitely has its place (and I use them plenty), but I'd argue that this is not a great place to use it.使用 async/await 肯定有它的位置(我经常使用它们),但我认为这不是一个使用它的好地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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