异步函数 运行 顺序,为什么?
Async functions run sequential, why?
我对异步函数有点困惑。它说他们 return 一个承诺。承诺通常不会立即 运行 在其余代码之前,因为 javascript 使用 "run to completion" 方法。
但是如果异步函数 return 一个 promise,你怎么解释这个?
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
在我看来,输出应该是:start > end > starting... > stopping!
因为承诺 运行 并发并且它们被放置在事件循环的末尾。
我知道那些方法仍然是同步的,但这不是主题。我目前正在从同步的 nodejs 方法转向异步方法。我只是问如果异步方法 return 一个承诺,它是如何在 end
console.log 语句之前 运行s 的?
But if async functions return a promise, how can you explain this?
一个 async
函数运行 同步 直到第一个 await
或 return
(包括隐式 return)。 (当我说 "up to," 时,同步部分包括 await
或 return
右边的操作数。)在那一点(await
或 return
),它return这是一个承诺。这样它就可以 启动 它应该启动的任何异步进程。这包含在规范 here.
中
你的 _prefixJS
不包含任何 await
或 return
,所以它同步运行到最后,returning 一个将被履行的承诺值 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!');
};
有了那个函数,console.log('running');
调用和 fsp.copyFile(...)
调用在调用 _prefixJS
时同步完成,然后函数 return 承诺并等待fsp.copyFile(...)
在异步继续其逻辑之前的结果。
fsp
函数使用占位符的实例:
const doWork = () => new Promise(resolve =>
setTimeout(resolve, Math.random() * 2000));
const fsp = {
async copyFile() {
console.log("copyFile started");
await doWork();
console.log("copyFile returning");
},
async readFile() {
console.log("readFile started");
await doWork();
console.log("readFile returning");
},
async writeFile() {
console.log("writeFile started");
await doWork();
console.log("writeFile returning");
}
};
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!');
};
console.log("calling _prefixJS");
_prefixJS()
.then(() => {
console.log("then handler on _prefixJS()");
})
.catch(error => {
console.log(`catch handler on _prefixJS(): ${error.message}`);
});
console.log("calling _prefixJS - done");
我对异步函数有点困惑。它说他们 return 一个承诺。承诺通常不会立即 运行 在其余代码之前,因为 javascript 使用 "run to completion" 方法。
但是如果异步函数 return 一个 promise,你怎么解释这个?
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
在我看来,输出应该是:start > end > starting... > stopping!
因为承诺 运行 并发并且它们被放置在事件循环的末尾。
我知道那些方法仍然是同步的,但这不是主题。我目前正在从同步的 nodejs 方法转向异步方法。我只是问如果异步方法 return 一个承诺,它是如何在 end
console.log 语句之前 运行s 的?
But if async functions return a promise, how can you explain this?
一个 async
函数运行 同步 直到第一个 await
或 return
(包括隐式 return)。 (当我说 "up to," 时,同步部分包括 await
或 return
右边的操作数。)在那一点(await
或 return
),它return这是一个承诺。这样它就可以 启动 它应该启动的任何异步进程。这包含在规范 here.
你的 _prefixJS
不包含任何 await
或 return
,所以它同步运行到最后,returning 一个将被履行的承诺值 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!');
};
有了那个函数,console.log('running');
调用和 fsp.copyFile(...)
调用在调用 _prefixJS
时同步完成,然后函数 return 承诺并等待fsp.copyFile(...)
在异步继续其逻辑之前的结果。
fsp
函数使用占位符的实例:
const doWork = () => new Promise(resolve =>
setTimeout(resolve, Math.random() * 2000));
const fsp = {
async copyFile() {
console.log("copyFile started");
await doWork();
console.log("copyFile returning");
},
async readFile() {
console.log("readFile started");
await doWork();
console.log("readFile returning");
},
async writeFile() {
console.log("writeFile started");
await doWork();
console.log("writeFile returning");
}
};
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!');
};
console.log("calling _prefixJS");
_prefixJS()
.then(() => {
console.log("then handler on _prefixJS()");
})
.catch(error => {
console.log(`catch handler on _prefixJS(): ${error.message}`);
});
console.log("calling _prefixJS - done");