【问题标题】:await promise before callback in async.each在 async.each 回调之前等待承诺
【发布时间】:2019-03-31 10:13:24
【问题描述】:
router.post('/runCommand', async function(req, res){
  let results = [];
  async.each(req.body.requests, async function(request, callback){
    const data = await connect(request.command)
    await results.push(data);
    await callback(null);
  }, function(err){
    if (!err) {
      res.send(202, results)
    }
  })
})

Res.send 永远不会发生,并且回调似乎在连接完成运行之前发生。 Connect 成功返回了一个 Promise,因为这个

router.get('/topics', async function(req, res) {
  console.log('in get');
  const data = await connect(req.body.command);
  await res.send(data);
});

工作正常。但包括运行多个命令的 async.each 似乎已损坏。我知道这是我如何调用 async.each 回调函数的问题,但研究还没有利用我应该如何调用它。等待承诺后是否可以使用.then()

function connect(command){
  return new Promise(function(resolve) {
  let host = {
        server: {
          host: "host",
          port: "port",
          userName: "user",
          password: config.Devpassword
        },
        commands: [ command ]
      };
  var SSH2Shell = require ('ssh2shell'),
  //Create a new instance passing in the host object
  SSH = new SSH2Shell(host),
  //Use a callback function to process the full session text
  callback = function(sessionText){
    console.log(sessionText)
    resolve(sessionText);
  }
  SSH.connect(callback);
  })
};

【问题讨论】:

  • 您对async.each() 的回调是否被调用过?如果是这样,报告的错误是什么?这里没有足够的信息来确定你哪里出错了。您确定您的 POST 请求的 req.body 将被格式化为 { requests: [ { command: ... }, ...] }
  • 我可以通过连接函数中的控制台日志知道它正在为 req 中的每个命令发生。是的,这是正确的格式。我遇到的问题是运行回调的时间。我不等待连接完成运行。所以 async.each 在正确定义结果数组之前会遍历 req 中的每个命令。虽然我不确定为什么 res.send 永远不会发生。我以为它只会发送一系列未履行的承诺,但实际上根本没有发送
  • 请通过edit提供connect()的来源@您的答案。问题似乎就在那里。
  • 而您在req.body.requests 中为每个request 获得console.log(sessionText)
  • @PatrickRoberts 我添加了connect() 的来源,尽管我不相信问题存在。它返回一个承诺罚款。当我只使用另一个函数运行单个命令时,它会在 res.sending 会话文本之前正确等待它完成。我认为问题在于我如何从 async.each 调用 callback()

标签: javascript callback async-await es6-promise async.js


【解决方案1】:

虽然您可以继续花更多时间让async.each() 工作,但我建议您放弃它并专门使用async / await 语法,这大大简化了您的代码:

router.post('/runCommand', async function (req, res) {
  try {
    const results = await Promise.all(
      req.body.requests.map(({ command }) => connect(command))
    );

    res.send(202, results);
  } catch ({ message, stack }) {
    res.send(500, { error: message, stack });
  }
})

查看ssh2shell 文档,我认为您的connect 函数也可以改进,以获得更好的可读性和错误处理:

const SSH2Shell = require('ssh2shell');

function connect (command) {
  return new Promise((resolve, reject) => {
    const host = {
      server: {
        host: 'host',
        port: 'port',
        userName: 'user',
        password: config.Devpassword
      },
      commands: [command]
    };
    //Create a new instance passing in the host object
    const SSH = new SSH2Shell(host);

    SSH.on('error', reject);
    SSH.connect(resolve);
  });
}

如果这仍然不适合您,请随时发表评论。

【讨论】:

  • 谢谢!关于简化,您 100% 正确。我肯定会使用它,但当我有更多时间时可能会研究 async.each。
猜你喜欢
  • 1970-01-01
  • 2020-04-22
  • 2017-11-23
  • 1970-01-01
  • 2017-07-31
  • 2023-02-17
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多