首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按顺序从嵌套循环执行异步处理功能

按顺序从嵌套循环执行异步处理功能
EN

Stack Overflow用户
提问于 2019-03-21 18:45:24
回答 2查看 46关注 0票数 0

我有一个函数,可以将大量数据保存在数据库中。回调将在结束时异步调用。

代码语言:javascript
复制
function process(..., fn) {
  saveInDB(function(err, results) {
    // ...
    // fn() or fn(err)
  })
}

该函数从嵌套循环中多次调用。

代码语言:javascript
复制
for (const x of arrays) {
  const space1 = x[0]
  for (const y of x.slice(1)) {
    const space2 = y[0]
    for (const z of y[1]) {
      process(space1, space2, z, fn)
    }
  }
}

该问题要求下一次调用仅在上一次成功的情况下发生。这里是我的累赘实现。

代码语言:javascript
复制
let calls = []
for (const x of arrays) {
  const space1 = x[0]
  for (const y of x.slice(1)) {
    const space2 = y[0]
    for (const z of y[1]) {
      calls.push((fn) => () => process(space1, space2, z, fn))
    }
  }
}

let call = null

for (let i = calls.length - 1; i >= 0; --i) {

  if (i === calls.length - 1) {
    call = calls[i](err => {
      if (!err)
        return finalCallback(null, { 'status': 'success' })
      log.error(err)
      finalCallback(err)
    })
    continue
  }

  const lastNext = call
  call = calls[i](err => {
    if (!err)
      return lastNext()
    finalCallback(err)
    log.error(err)
  })
}

if (call)
  call()

我正在寻求Javascript专业人士的建议,您是如何解决这类问题的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-21 19:09:30

使用async ... await

在您的用例中,使用await关键字将允许您在继续之前等待process返回的承诺解决。您必须将您的函数定义为async

您还需要使用try ... catch块来处理任何错误。

由于您的process函数目前没有返回承诺,因此您需要修改它才能这样做。

示例:

代码语言:javascript
复制
function process(/* your args */) {
  return new Promise((resolve, reject) => {
    saveInDB((err, results) => {
      if (err) {
        reject(err)
      } else {
        resolve(results)
      }
  })
}

// now for the `async ... await`
async function myFunc(arrays) {
  for (const x of arrays) {
    const space1 = x[0]
    for (const y of x.slice(1)) {
      const space2 = y[0]
      for (const z of y[1]) {
        try {
          // This will wait until your `process` has finished
          await process(space1, space2, z, fn)
        } catch (error) {
          // handle any errors
          console.log(error)
          // if you would like to bail after an error you can `return`
          return
        }
      }
    }
  }
}

但是,既然您的函数存在,就可以使用它了,因此它是异步的,因此它不会阻止任何代码在运行之后运行,因此您应该做以下两件事中的一件:

  1. await您的电话到myFunc
  2. 将任何依赖saveInDB完成的代码放在.then()中。
代码语言:javascript
复制
myFunc(/* your arrays */)
  .then(() => {
    // your function has finished
  })
票数 1
EN

Stack Overflow用户

发布于 2019-03-21 19:08:53

saveToDB通常会使用一些表示数据的参数;我只是假设它需要一个数据参数和一个回调,但是可以根据需要进行调整。

首先要证明这一功能。您使用的API可能已经支持承诺,这意味着如果回调函数没有传递给它,上面的函数将返回一个承诺。但是如果不是这样的话,您可以创建自己的promisified:

代码语言:javascript
复制
// promisify the saveInDB function:
const process = (data) => new Promise((resolve, reject) =>
    saveInDB(data, (err, results) => err ? reject(error) : resolve(results))
);

然后创建一个async函数,以便您可以使用await

代码语言:javascript
复制
async function task(arrays) {
    for (const x of arrays) {
        const space1 = x[0]
        for (const y of x.slice(1)) {
            const space2 = y[0]
            for (const z of y[1]) {
                await process([space1, space2, z])
            }
        }
    }
}

..。然后打电话给我。它回报了你的承诺,这样你就可以处理满足和拒绝:

代码语言:javascript
复制
task(arrays).then(() => console.log("all done"))
            .catch((err) => console.log("error occurred", err));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55287288

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档