Promise も async function も 同期実行される範囲があります。
これを実行したらどう実行されるかわかりますでしょうか?
console.log('1');
new Promise(resolve => {
console.log('2');
resolve();
});
console.log('3');
これを実行したらどう実行されるかわかりますでしょうか?
console.log('1');
(async function() {
console.log('2');
})();
console.log('3');
答えは
1
2
3
です。
なぜなら
- Promise コンストラクタは同期実行されるから
- async await に於いて、非同期になるのは await されたときから
だからです
とりあえず同期で動いてほしくないならこれでいいです。
console.log('1');
Promise.resolve()
.then(() => console.log('2'));
console.log('3');
1
3
2
これと同等の処理を Promise コンストラクタを使って書くならこうです
console.log('1');
new Promise(resolve => resolve())
.then(() => console.log('2'));
console.log('3');
async function を使って書くならこうなります
console.log('1');
(async function () {
await Promise.resolve();
console.log('2');
})();
console.log('3');
これは Promise を使わずに書くならこうなります
console.log('1');
queueMicrotask(() => console.log('2'));
console.log('3');
ちなみに queueMicrotask の polyfill は次の様な実装です、
if (typeof globalThis.queueMicrotask !== "function") {
globalThis.queueMicrotask = function (callback) {
Promise.resolve()
.then(callback)
.catch((e) =>
setTimeout(() => {
throw e;
}),
);
};
}
つまり、 非同期実行してほしい場合は Promise.prototype.then() ……つまり await しろって話です。
以上。
追伸
この実行順序はわかりますよね?
console.log('1');
new Promise(resolve => {
console.log('2');
resolve();
})
.then(() => console.log('6'));
console.log('3');
(async function () {
console.log('4');
await null;
console.log('7');
})();
console.log('5');
See the Pen Untitled by juner clarinet (@juner) on CodePen.
参考