开发者问题收集

为什么这些 .then() 出现的顺序不对?

2017-11-17
68

我有一个节点应用程序,它 生成 一个 child_process 。当 child_process 运行完毕时,我想解决一个承诺。以下代码有效,但 .then() 语句出现顺序错误:

const storage = require('./storage');
const logging = require('./logging');
const process = require('child_process').spawn;


function convertIncomingFile(pathToFile) {
  logging.info(`Converting ${pathToFile}`);
  const convert = process(`cat`, [pathToFile], {});

  return Promise.resolve(
    convert.stdout.on('data', (data) => {
      logging.info(data.toString('utf8'));
    }),
    convert.stderr.on('data', (err) => {
      logging.error(err);
    }),
    convert.on('close', (code) => {
      logging.info(`Conversion finished with status code ${code}`);
    })
  );
}

module.exports = {
  convertFile: (filename) => {
    storage.downloadFile(filename).
      then((localFilename) => {
        logging.info(`File saved to: ${localFilename}`);
      }).
      then(() => convertIncomingFile(`./files/${filename}`)).
      then(() => {
        logging.info(`Coversion of ${filename} complete.`);
      }).
      catch((apiErr) => {
        logging.error(apiErr);
      });
  }
};

我得到的输出是:

info: File saved to: ./files/package.json
info: Converting ./files/package.json
info: Coversion of package.json complete.
info: {
 <file contents>
}

info: Conversion finished with status code 0

如您所见, Conversion of package.json complete. 语句发生在文件内容记录和转换状态代码语句之前。为什么会出现这种情况?我如何让“转换完成”语句出现在“状态代码”语句之后?

2个回答

Promise.resolve 表示返回您指定的已解决值,它并不像您预期​​的那样真正异步。请查看 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 了解详细信息

function convertIncomingFile(pathToFile) {
  logging.info(`Converting ${pathToFile}`);
  const convert = process(`cat`, [pathToFile], {});

  return new Promise((resolve, reject) => {
    convert.stdout.on('data', (data) => {
        logging.info(data.toString('utf8'));
      }),
      convert.stderr.on('data', (err) => {
        logging.error(err);
        reject()
      }),
      convert.on('close', (code) => {
        logging.info(`Conversion finished with status code ${code}`);
        resolve()
      })
  })
}
Josh Lin
2017-11-17

您必须进一步传递 convertFile 承诺,以便让下一个 then 知道它必须等待:

then(() => {
  return convertFile(`./files/${filename}`);
})

以及更短的等效代码:

then(() => convertFile(`./files/${filename}`))
hsz
2017-11-17