Можете ли вы помочь мне понять, как работает async await в Node.js ?

#javascript #node.js #asynchronous #hubot

#javascript #node.js #асинхронный #hubot

Вопрос:

Я пытаюсь написать скрипт в Node для hubot, который запускает команды на удаленном сервере, чтобы получить текущие версии различного стороннего программного обеспечения, установленного в данный момент на этом сервере.

Моя проблема связана с завершением моей функции getVersions, которая вызывает функцию getVersionsOverSSH. Однако массив versions не ожидает завершения вызываемой функции перед попыткой распечатать содержимое versions. Я не очень опытен в Node, поэтому мое понимание того, как работает await / async, ограничено. Может кто-нибудь сказать мне, как запустить этот скрипт синхронным образом, чтобы он ожидал завершения SSH-функции, прежде чем двигаться дальше? Спасибо

getVersions.js

 versions = [];

async function getVersions(res) {
  const env = getEnvsFromRequest(res.match[2].toString());
  const resEnv = resolver.resolveEdiEnv(env);
  if (resEnv === null) {
    res.reply(`${env} is not in my list of available environments.`);
    return;
  }
  if (resEnv.length > 0) {
    response = response.concat(`nHere are the results for ${resEnv}:n`);
  }
  
  // Resolve hosts for environment
  let resHosts = [];
  resHosts = await resolver.resolveHosts(resEnv);
  // Resolve creds for environment
  let resCreds = [];
  resCreds = await resolver.resolveCreds(resEnv);
  
  try {
    versions = await getVersionsOverSSH(resHosts,resCreds);
    console.log(versions) // this line prints before array is loaded
  } catch (err) {
    console.log(err);
  }
}
  
 // function that makes the ssh calls and appends verions into an array
//  returns array complete with versions from each command

function getVersionsOverSSH(resHosts,resCreds) {
    
  dummy = [];
  const ssh = new SSH({
    host: resHosts[1],
    user: resCreds[0],
    pass: resCreds[1]
  });
  ssh
    // Software 1 version
      .exec('head -3 /app/foo/bar | tail -1 | cut -d '=' -f 2', {
        out(stdout) { dummy.push(`Software 1 version: ${stdout}`); },
      })
    // Software 2 version
      .exec('cd /app/foo/foo/bar amp;amp; ls -td -- * | head -n 1', {
        out(stdout) { dummy.push(`Software 2 version: ${stdout}`); },
      })
    // Software 3 Version
      .exec(`cd /app/foo/bar/foo amp;amp; ./version.sh | grep Foo* | cut -d ' ' -f 3`, {
        out(stdout) { dummy.push(`Software 3: ${stdout}`); },
      })
      .start();
  
  console.log(dummy); // this prints correctly
  return dummy;
}
  

Комментарии:

1. Какая строка печатается первой? console.log(фиктивный) из getVersionsOverSSH или console.log (версии) из getVersion.js

2. @KrunalSonparate сначала печатается console.log (версии), но это пустой массив. Функция getVersions — это то, что изначально вызывается hubot

3. какую ssh-библиотеку вы используете? Если функция exec возвращает обещание, то вам нужно вернуть фиктивный массив из функции then в конце конвейера и нужно вернуть весь конвейер

4. @KrunalSonparate Я использую simple-ssh. Извините, вероятно, следовало упомянуть об этом. Было бы мне лучше использовать библиотеку со встроенными обещаниями, такими как node-ssh?

5. Да, я бы предложил использовать библиотеку на основе обещаний, такую как node-ssh

Ответ №1:

Вам нужно вернуть promise и разрешить его при необходимости. И execSync внутри getVersionsOverSSH

 function getVersionsOverSSH(resHosts,resCreds) {
  return new Promise((resolve, reject) => {
    dummy = [];
    const ssh = new SSH({
      host: resHosts[1],
      user: resCreds[0],
      pass: resCreds[1]
    });
    ssh
      // Software 1 version
      .execSync('head -3 /app/foo/bar | tail -1 | cut -d '=' -f 2', {
        out(stdout) { dummy.push(`Software 1 version: ${stdout}`); },
      })
      // Software 2 version
      .execSync('cd /app/foo/foo/bar amp;amp; ls -td -- * | head -n 1', {
        out(stdout) { dummy.push(`Software 2 version: ${stdout}`); },
      })
      // Software 3 Version
      .execSync(`cd /app/foo/bar/foo amp;amp; ./version.sh | grep Foo* | cut -d ' ' -f 3`, {
        out(stdout) { dummy.push(`Software 3: ${stdout}`); },
      })
      .start();
  
      console.log(dummy); // this prints correctly
    //
    resolve(dummy);
  });
}