ждите обещание перед обратным вызовом в async.each

1
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 успешно возвращает обещание, потому что это

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);
  })
};
  • 0
    Ваш обратный вызов async.each() когда-либо вызывался? Если да, то что было ошибкой? Здесь недостаточно информации, чтобы определить, где вы идете не так. Вы уверены, что req.body вашего POST-запроса будет отформатировано как { requests: [ { command: ... }, ...] } ?
  • 0
    Я могу сказать по логам консоли в функции подключения, что это происходит для каждой команды в req. и да, это правильный формат. Проблема, с которой я сталкиваюсь, заключается в том, когда выполняется обратный вызов. Я не жду соединения, чтобы закончить бежать. поэтому async.each проходит через каждую команду в req до того, как массив результатов будет правильно определен. Хотя я не уверен, почему res.send никогда не происходит. Я предполагал, что это просто отправит и массив невыполненных обещаний, но на самом деле никогда не отправляет вообще
Показать ещё 10 комментариев
Теги:
callback
async-await
es6-promise
async.js

1 ответ

1
Лучший ответ

Хотя вы можете продолжать async.each() больше времени работе 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);
  });
}

Пожалуйста, не стесняйтесь комментировать, если это все еще не работает для вас.

  • 0
    Спасибо! Вы были на 100% правы об упрощении. Я определенно буду использовать это, но могу посмотреть на async.each, когда у меня будет больше времени.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню