最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Wait for map to end before continuing - Stack Overflow

programmeradmin1浏览0评论
  let shouldHavePaid = 0;

  demographicsArray.map((country) => {
    if (country.checked == true) {
      Price.findOne({ country: country._id }).then((priceRes) => {
        if (priceRes) {
          shouldHavePaid = shouldHavePaid + priceRes.priceSMS * country.count;
        } else {
          shouldHavePaid = shouldHavePaid + 0.1 * country.count; //Default price for unlisted countries
        }
      });
    }
  });

  console.log(`Finish: ${shouldHavePaid}`);

I want the console.log at the end to execute after the map, but it fires before the map is finished. I am expecting this output because as far as I know map should be sync and not async. I believe that the request to the DB messes it up? what would you suggest here?

  let shouldHavePaid = 0;

  demographicsArray.map((country) => {
    if (country.checked == true) {
      Price.findOne({ country: country._id }).then((priceRes) => {
        if (priceRes) {
          shouldHavePaid = shouldHavePaid + priceRes.priceSMS * country.count;
        } else {
          shouldHavePaid = shouldHavePaid + 0.1 * country.count; //Default price for unlisted countries
        }
      });
    }
  });

  console.log(`Finish: ${shouldHavePaid}`);

I want the console.log at the end to execute after the map, but it fires before the map is finished. I am expecting this output because as far as I know map should be sync and not async. I believe that the request to the DB messes it up? what would you suggest here?

Share Improve this question asked Jun 29, 2020 at 15:17 PastaLoverPastaLover 4915 silver badges22 bronze badges 3
  • 3 1. Please don't use .map for a simple iteration. Use a loop or .forEach for that. 2. .map is a synchronous operation, but you are launching asynchronous ones inside it. You either need to make all async and use Promise.all and wait for all of the pletion (parallel) or convert to a regular loop and await every iteration (sequential). You can also reduce to a single sequential operation but I'd probably go with the loop. – VLAZ Commented Jun 29, 2020 at 15:21
  • Thanks, and why do you suggest not to use map for simple iterations? For the ability to use await? – PastaLover Commented Jun 29, 2020 at 15:46
  • 1 It's the wrong tool and it's misleading. Mapping operations are 1:1 transformations. Using it for anything else is sending the wrong message to anybody who would be looking at the code in the future, including yourself. .map is an idiom in JavaScript and many other languages. There are many other better idioms for mon array operations. Check my profile information. – VLAZ Commented Jun 29, 2020 at 15:51
Add a ment  | 

2 Answers 2

Reset to default 6

You can use Promise.all in bination with await:

await Promise.all(demographicsArray.map(async (...)=>{
    if (...) {
        await Prize... 
        if (priceRes) {
            ....
        }
    }
})

console.log(...)

Await can be used in async functions to run the next line only after the promise pletes. Promise.all() allows you to wait for a whole array of promises. Marking the callback as async makes it return a promise, that can be used by the Promise.all(). It also allows you to use await inside the function so you don't have to use .then().

Well, you are saying it your self pretty much

I am expecting this output because as far as I know map should be sync and not async. I believe that the request to the DB messes it up?

Your Price.findOne(expr) returns a promise, so this part is async, so this is the root of your problem.

For your console.log to e at the end, and without making restructs to your code, just put it after the actuall record if fetched and the data pared!

 let shouldHavePaid = 0;

  demographicsArray.map((country) => {
    if (country.checked == true) {
      Price.findOne({ country: country._id }).then((priceRes) => {
        if (priceRes) {
          shouldHavePaid = shouldHavePaid + priceRes.priceSMS * country.count;
        } else {
          shouldHavePaid = shouldHavePaid + 0.1 * country.count; //Default price for unlisted countries
        }
  console.log(`Finish: ${shouldHavePaid}`);
      });
    }
  });
发布评论

评论列表(0)

  1. 暂无评论