异步函数按顺序运行,为什么?

cod*_*leb 1 javascript promise async-await es6-promise

我对异步函数有点困惑。它说他们返回一个承诺。承诺通常不会在其余代码之前立即运行,因为 javascript 使用“运行到完成”方法。

但是如果异步函数返回一个承诺,你怎么解释呢?


const _prefixJS = async file => {
  console.log('running...')
  fs.copyFileSync(file, `${file}.bak`);
  const content = fs.readFileSync(file, 'utf8');
  // Some modifications...
  fs.writeFileSync(file, newContent);
  console.log('stopping!')
};

console.log('start')
_prefixJS(f);
console.log('end')

// Output: start > running... > stopping! > end
Run Code Online (Sandbox Code Playgroud)

在我看来,输出应该是: start > end > starting... > stopping!

因为 promise 是并发运行的,并且它们被放置在事件循环的末尾。

我知道这些方法仍然是同步的,但这不是主题。我目前正在从同步 nodejs 方法转向异步方法。我只是问,如果异步方法返回一个承诺,它是如何在endconsole.log 语句之前运行的?

T.J*_*der 5

但是如果异步函数返回一个承诺,你怎么解释呢?

一个async函数同步运行到第一个awaitor return(包括隐式返回)。(当我说“最多”时,同步部分包括await或右侧的操作数return。)在这一点上(awaitreturn),它返回一个承诺。这样它就可以启动它应该启动的任何异步进程。这在此处的规范中有所涉及。

你的_prefixJS不包含任何awaitor return,所以它同步运行到最后,返回一个将用 value 实现的承诺undefined

为了使您的async函数真正异步工作,您需要使用fs.promises这些函数的版本await及其结果。像这样的东西(未经测试):

const fsp = require("fs").promises;
// ...
const _prefixJS = async file => {
  console.log('running...');
  await fsp.copyFile(file, `${file}.bak`);
  const content = await fsp.readFile(file, 'utf8');
  // Some modifications...
  await fsp.writeFile(file, newContent);
  console.log('stopping!');
};
Run Code Online (Sandbox Code Playgroud)

使用该函数,console.log('running');调用和fsp.copyFile(...)调用在_prefixJS被调用时同步完成,然后函数返回其承诺并在fsp.copyFile(...)异步继续其逻辑之前等待结果。

fsp函数使用占位符的实时示例:

const fsp = require("fs").promises;
// ...
const _prefixJS = async file => {
  console.log('running...');
  await fsp.copyFile(file, `${file}.bak`);
  const content = await fsp.readFile(file, 'utf8');
  // Some modifications...
  await fsp.writeFile(file, newContent);
  console.log('stopping!');
};
Run Code Online (Sandbox Code Playgroud)