异步等待在地图功能内无法正常工作 [英] Async await not work properly inside map function

查看:92
本文介绍了异步等待在地图功能内无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的数据集结构:

I have a Dataset Structure like this:

  _id: SomeMongoID,
  value: "a",
  counter: 1
}

因此,最初我的数据库表为空.现在我有一个数组,其中的值是这样的: const array = ["a","a","a"]

So initially my database table is empty. Now I have an array where value is like: const array = ["a", "a", "a"]

我想要的最初是我第一次搜索,因此它将清空结果,因此在这种情况下,插入查询,现在下一次它得到条目时,只需增加计数器即可.

What I want is initially the first time I do the search, so it will empty result so at that case in insert the query, now next time it get the entry so simply increment the counter.

为此,我编写了代码:

const testFunction = async(array) => {
  try {
    await Promise.all(
      array.map(async x => {
       const data = await CollectionName.findOne({value: x}).exec();
       // Every time data will return null
       if (data) {
         //In this case only counter will have to increase
         // But this block not run 
       } else {
         //So by this first value will store
         const value = new Value({
          value: x,
          counter: 1
         });
         await value.save()
       }
      })
    )
  } catch (error) {
    console.log(error)
  }
}
const array = ["a", "a", "a"]
testFunction(array);

问题是它将创建3个条目而不是单个条目.map函数不会等待,我使用console.log()通过手动调试进行了检查.任何帮助或建议都非常感激.

Problem is it will create the 3 entry not single. map function will not wait, I checked through manual debugging using console.log(). Any help or suggestion is really appreciated.

推荐答案

要节省时间并并行加载数据,请先处理我们拥有的值.我们创建了一个数据结构,该数据结构甚至在单次调用数据库之前就已经计数了相同的值.然后,我们仅在数据库中为数据结构中的唯一键调用数据库.这样可以将您的示例中的调用次数从3个减少到1个.在我的示例中,我向测试数据中添加了两个"b" 值.因此通话次数将是2而不是5.

To save time and load data in parallel, first process the values we have ourselves. We create a data structure that has already counted the same values before even making a single call to the database. Then we only call the database for a unique key in our data structure. This reduces the number of calls in your example from 3 to 1. I my example i added two "b" values to the test data. So the number of calls will be 2 instead of 5.

然后在数据库中查询唯一键.如果找到条目,则将计数器增加测试数组中出现的 value 个值.如果未找到,则会创建一个新条目,并将计数器设置为已发现的出现次数.

The database is then queried for the unique keys. If an entry is found, the counter is increased by the number of value occurrences inside the test array. If it is not found a new entry is made with the counter set to the number of found occurences.

const testFunction = async (array) => {
  try {

    // Create a statistics by counting each value fist
    // Creates a structure like { a: 3, b: 2}
    const countsByValues = array.reduce((acc, value) => {
      const newCount = acc[value] ? acc[value] + 1 : 1;
      return {
        ...acc,
        value: newCount
      };
    }, {});

    await Promise.all(
      // Use object entries to get array of [["a", 3], ["b", 2]]
      Object.entries(countsByValues).map(async ([x, count]) => {
       const data = await CollectionName.findOne({value: x}).exec();
       if (data) {
         //In this case only counter will have to increase by the count
         data.counter += count;
         //save data - insert your code saving code here
         await data.save();
       } else {
         //So by this first value will store
         const value = new Value({
          value: x,
          // new values will be the total count
          counter: count
         });
         await value.save()
       }
      })
    )
  } catch (error) {
    console.log(error)
  }
}
const array = ["a", "a", "b", "b", "a"]
testFunction(array);

这篇关于异步等待在地图功能内无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆