【问题标题】:NodeJS Create an array of functions and execute it through async.seriesNodeJS 创建函数数组并通过 async.series 执行
【发布时间】:2020-01-05 06:08:58
【问题描述】:

从 NodeJS 的学习曲线开始,我尝试使用 async.series 调用一系列函数。每个函数都是一个使用 REST 远程调用的命令行。

function TestStorageDeviceBasic()
{
    scenario = [
        'cmdline1',
        'cmdline2'
    ];

    tasks = [];
    scenario.forEach(command => { tasks.push(RunCommand(sessionId,command));});
    async.series(tasks);
}

function RunCommand(sessionId, cmdLine)
{
    var options = {
        uri: `http://${domain}/api/v1/commands`,
        method: 'POST',
        json: {
            'session-id' : `${sessionId}`,
            'command-line': `${cmdLine}` 
        }
      };

      request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            log.debug(`\"${cmdLine}\" status code successful`)
            log.debug(body);
        }
        else
            log.error(`\"${cmdLine}\" status code failed`,error);
      });
}

尽管似乎调用了 RunCommand 函数,但我遇到了一些问题。

(node:21008) UnhandledPromiseRejectionWarning: Error: expected a function
    at wrapAsync (C:\work\MyJavascriptProject\my_sample\node_modules\async\dist\async.js:198:50)
    at C:\work\MyJavascriptProject\my_sample\node_modules\async\dist\async.js:2952:13

为什么 RunCommand 不被视为函数?

【问题讨论】:

  • 您正在 调用 RunCommand 并将函数的结果推送到任务中。 RunCommand 的结果不是函数。您可以尝试使用.bind() 使用捕获的参数创建一个函数。
  • 关于使用异步第三方的评论:最好使用异步等待(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

标签: node.js async.js


【解决方案1】:

代码中需要修改三处

  • 将 RunCommand 包装在一个函数中,然后将其推送到任务数组中
  • 确保在结束时传递回调
  • 修改RunCommand 使其也具有回调,以便async.series 可以使用回调的输出。

由于您没有为 RunCommand 传递回调,因此它只会执行一次,因为 async.series 不知道何时继续。修改后的代码如下所示

function TestStorageDeviceBasic() {
  scenario = ["cmdline1", "cmdline2"];

  tasks = [];
  scenario.forEach(command => {
    tasks.push(callack => RunCommand(sessionId, command, callack));
  });
  async.series(tasks, (err, data) => {
    if (err) {
      console.error(err);
    }
    console.log(data);
  });
}

function RunCommand(sessionId, cmdLine, callack) {
  var options = {
    uri: `http://${domain}/api/v1/commands`,
    method: "POST",
    json: {
      "session-id": `${sessionId}`,
      "command-line": `${cmdLine}`
    }
  };

  request(options, function(error, response, body) {
    if (!error && response.statusCode == 200) {
      log.debug(`\"${cmdLine}\" status code successful`);
      log.debug(body);
      callack(null, body);
    } else {
      log.error(`\"${cmdLine}\" status code failed`, error);
      callack(error, null);
    }
  });
}

希望对你有帮助

【讨论】:

  • 谢谢。因此,当这样做时,我会通过堆栈跟踪得到“错误:回调已被调用”。这是我最后一个小时被困的地方。
  • 您到底在哪里得到这个错误?它对我来说很好。看到这个 - repl.it/repls/PrevailingAshamedUtilities 不完全一样,但足以给你一个想法
  • 会不会是因为下一行使用的是err 而不是error?我已经更新了代码。同样值得检查log.error 行是否没有给出任何错误。
  • 我的代码中有一个愚蠢的错误,例如缺少大括号并且回调始终是代码。完美,非常感谢。
【解决方案2】:

这是因为您调用RunCommand,然后将其返回值推入tasks。相反,推送一个进行调用的函数:

scenario.forEach(command => { 
    tasks.push(() => RunCommand(sessionId,command));
});

【讨论】:

  • 实际上确实解决了问题,但是在调用 async.series(tasks) 之后只调用了第一个函数
  • @isaac.hazan - 看到我的回答,这解释了为什么你会看到这种行为。希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 2023-03-14
  • 2020-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
相关资源
最近更新 更多