web-dev-qa-db-ja.com

私の場合、なぜ `async / await`が機能しないのですか?

async/awaitについて読みましたが、重要な質問があります。最初に古い例を説明して質問のベースを示し、次に正確な質問をします。

誰もがそれを知っています:

console.log('1');
console.log('2');
console.log('3'); // Ex: 123

簡単ですが、以下の場合です。

console.log('1');
setTimeout(()=>{
    console.log('2');
},0);
console.log('3'); // Ex: 132

setTimeout関数はasynchronousであり、JavaScriptはそこからジャンプし、解決後にその関数を実行するので、2の後に1が表示されます。および3

しかし、今私はasync/awaitを読み、次のような関数を作成しました。

(async function test() {
    console.log('1');
    await setTimeout(()=>{
        console.log('2');
    },0);
    console.log('3');
})(); // Ex: 132

エクスポートも132ですが、なぜですか?これが私の質問です。なぜ32の前に実行されるのですか? async/awaitJavaScriptが1を待ってから、2を書き込んだ後の3のために期待しています。なぜ132

5
user9289032

awaitは、渡された値がPromiseの場合にのみ一時停止します。あなたの場合、setTimeoutNumberを返すので、awaitはそれを待ちません。

正しいコードは次のとおりです。

async function test() {
    console.log('1');
    await new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('2');
            resolve()
        }, 0);
    });
    console.log('3');
}
9
Ayush Gupta

setTimeoutはpromiseを返さないためです。 _await x_は、xが約束である場合にのみ待機します。 xが約束でない場合は、await Promise.resolve(x)があるかのように(事実上)1つにラップされます。つまり、それに続くコードは非同期で実行されますが、できるだけ早く実行されます。*

setTimeoutのpromiseバージョンが必要な場合は、 この質問の回答 を参照してください。しかし、それでも、test関数はコールバックを使用せず、代わりに、promiseが有効なタイムアウトを待つだけです。

_function later(delay) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay);
    });
}

async function test() {
  console.log("1");
  await later(10);
  console.log("2");
  console.log("3");
}

test().catch(e => console.error(e));
console.log("After the call (just to prove it does wait for the timeout after 1 and before 2");_

*ブラウザでは、同じタスク中にスケジュールされたsetTimeout(..., 0)の前にあることが保証されます。これは、タスク中にスケジュールされたpromiseコールバックが、そのタスクの終了直後、次のタスクがキューから取得される前に発生するためです(次のタスクがpromiseコールバックの前にスケジュールされていたとしても)。これについての詳細(「マクロタスク」と「マイクロタスク」) この質問の回答

2
T.J. Crowder

awaitを返す関数にPromiseすることができます。 setTimeoutPromiseを返しません。したがって、この場合、awaitの前に使用されるsetTimeoutには意味がありません。

setTimeoutをPromiseにラップし、setTimeout関数でresolveを呼び出すことができます。

(async function test() {
    console.log('1');
    await new Promise((resolve, reject) => { 
         setTimeout(() => {
            console.log('2');
            resolve(); // also can pass a parameter here to get it via await.
         },0);
    });
    console.log('3');
})();
1
Suren Srapyan