同步迭代无法在JavaScript中运行

时间:2017-04-29 05:13:40

标签: javascript sails.js waterline async.js

我正在尝试遍历数组并为每个iteratee创建记录。这就是我在这里提到的另一个问题:

async.each(data, (datum, callback) => {
  console.log('Iterated')

  Datum.create({
    row: datum,
  }).exec((error) => {
    if (error) return res.serverError(error)
    console.log('Created')
    callback()
  })
})

不幸的是,它导致了这个:

Iterated
Iterated
Iterated
Created
Created
Created

这不是想要的:

Iterated
Created
Iterated
Created
Iterated
Created

我做错了什么?

3 个答案:

答案 0 :(得分:2)

看起来像Datum.create是一个异步函数。 forEach遍历数组的三个元素中的每一个,依次记录它们。由于JavaScript在返回异步事件之前不会阻塞,因此您依次获取每个console.log。 然后在一些的时间后,结果进入并且"创建"登录到控制台。

答案 1 :(得分:2)

async.eachSeries()将一次运行一次迭代并等待每次迭代终止,然后再继续下一步。

  

我在每次创建之前创建一个唯一的用户友好标识符(如1,2,3等)。为此,我要查询数据库以找到最新的标识符并增加它,因为记录几乎同时创建,因此无法使用它。

这听起来像是瓶颈。我不喜欢在系列中运行异步代码,因为这通常会降低进程的速度。这种方法怎么样:

  • 由于data您知道您需要多少个标识符。
  • 在后端实现一个函数,该函数不会在(包括必要的递增等)时创建单个但n这样的标识符,并将该数组返回到前​​端。现在,您可以使用/将预先计算的ID数组映射到数据阵列,以并行方式运行常规请求。

这应该将运行时间从(createAnId + request) * data.length减少到单次迭代的运行时间。由于所有这些请求都可以在并行中运行,因此大多数重叠。

答案 2 :(得分:1)

您似乎正在使用异步数据处理库。对于您想要获得的结果,您需要同步处理数据。以下是如何做到的:

data.forEach(function(datum) {
  console.log('Iterated')

  Datum.create({
    row: datum,
  }).exec((error) => {
    if (error) return res.serverError(error)
    console.log('Created')
    callback()
  })
})

您可能还想完全删除callback函数,因为数据是同步处理的。