невозможно завершить мой процесс после завершения. NodeJS - PullRequest
0 голосов
/ 18 марта 2020

Я работаю над программой Node JS для подключения к удаленному SFTP-серверу для копирования файлов журнала. Я использую этот пакет NPM. ssh2-sftp-client

const main = () => {
  const servers = ['server list'];
  servers.forEach((s) => {
    const sftp = new Client();
    // Connect to the server
    sftp.connect({
      host: s,
      port: '22',
      username: '',
      password: '',
    }).then(() => logger.log(`Connected to ${s}`))
      // get list of directories
      .then(() => sftp.list(rootLogPath))
      .then((dirs) => {
        dirs.forEach((d) => {
          const target = createTargetDirectory(d.name);
          // list all files in the directory
          sftp.list(`${rootLogPath}/${d.name}`)
            .then((files) => {
              // filter only today's files
              const todayFiles = files.filter((f) => f.type === '-' && moment().format('MMDDYYYY') === moment(f.modifyTime).format('MMDDYYYY'));
              // copy today's files into target
              todayFiles.forEach((f) => {
                sftp.get(`${rootLogPath}/${d.name}/${f.name}`, `${target}/${f.name}`)
                  .then(() => logger.log(`Copied ${f.name} from ${d.name} located on ${s}`));
              });
            });
        });
        return sftp.end();
      })
      .catch(() => logger.log(`Connection to ${s} failed`));
  });
};

main();

Код работает должным образом, но проблема в том, что я не могу завершить сеанс. Программа просто ждет после завершения операции копирования файлов. Вызов sftp.end() преждевременно закрывает соединение до завершения копирования. Если я удаляю эту программу, то просто ждет, когда копирование будет завершено.

Я не уверен, где написать строку sftp.end() для завершения программы.

РЕДАКТИРОВАТЬ 1: Обновлен код с помощью Promise. все и используя async / await сейчас.

Разделите мой код на части и теперь используйте async / await для лучшей читаемости. Программа сейчас заканчивается нормально. больше не нужно ждать или зависать, но проблема в том, что файлы не копируются. Я вижу консольное сообщение "Скопированные файлы из исходного каталога".

const copyTodayFiles = async (src) => {
  try {
    let fileList = await sftp.list(`${rootLogPath}/${src}`);
    fileList = fileList.filter(
      (f) => f.type === '-' && moment().format('MMDDYYYY') === moment(f.modifyTime).format('MMDDYYYY'),
    );
    const target = createTargetDirectory(src);

    if (target) {
      fileList.forEach(async (f) => {
        try {
          await sftp.get(`${rootLogPath}/${src}/${f.name}`, `${target}/${f.name}`);
          logger.log(`Copied ${f.name}`);
        } catch (error) {
          logger.log(`Failed to copy ${f.name}`);
        }
      });
      console.log(`Copied files from ${src}`);
    }
  } catch (error) {
    logger.log(`Failed to read files from ${src}`);
    logger.log(error);
  }
};

const workOn = async (server) => {
  sftp = new Client();

  const config = {
    host: server,
    port: '22',
    username: '',
    password: '',
  };

  try {
    await sftp.connect(config);
    logger.log(`Connection to ${server} is successful.`);
    const logDir = await sftp.list(rootLogPath);
    Promise.all(logDir.map((d) => copyTodayFiles(d.name))).then(() => sftp.end());
    // logDir.forEach(async (d) => copyTodayFiles(d.name));
  } catch (error) {
    logger.log(`Connection to ${server} failed.`);
    logger.log(error);
  }
};

const main = () => {
  const servers = ['server list'];
  Promise.all(servers.map((s) => workOn(s)));
};

main();

1 Ответ

0 голосов
/ 18 марта 2020

Короче говоря, когда у вас есть «цепочка» обещаний (a.then(() => b.then(() =>...) и вы хотите что-то сделать в конце, вы просто добавляете эту вещь к последнему .then обратному вызову.

Однако, если вы делаете несколько обещаний, вам нужно подождать, пока все они не будут выполнены, что вы можете сделать, используя Promise.all (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):

Promise.all([promise1, promise2]).then(...

Для этого вам необходимо преобразовать все ваши forEach вызовы в map вызовы, которые возвращают обещания, которые они создают. Как только вы это сделаете, операция map вернет массив этих обещаний, которые вы можете использовать с Promise.all.

...