3

私はJSの非同期動作を調べていましたが、ほとんどの場合うまくいきました。コードを同期的に実行する方法、JS のシングル スレッド、および setTimeout 内のコールバックなどのコールバックが Web ブラウザ API によってタイミングを計られ、後でタスク キューに追加される方法を理解しています。

イベント ループはコール スタックを常にチェックし、それが空の場合 (すべての同期コードが実行された場合) にのみ、タスク キューにキューイングされた関数を取得します。それらをコール スタックにプッシュし、実行します。

これは非常に簡単で、次のコードの理由です。

console.log('start');
setTimeout(() => console.log('timeout'), 0);
console.log('end');

を出力しますstart, end, timeout

promise について読み始めたとき、タイムアウト、間隔、イベントリスナーなどの通常の非同期コードよりも優先度が高く、代わりにジョブ キュー/マイクロタスク キューに配置されることがわかりました。イベント ループは、最初にそのキューに優先順位を付け、すべてのジョブを使い果たすまで実行してから、タスク キューに移動します。

これはまだ意味があり、次を実行することで確認できます。

console.log('start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');

これは を出力しますstart, end, promise, timeout。同期コードが実行され、thenコールバックがマイクロタスク キューからスタックにプッシュされて実行され、タスク キューから setTimeout コールバック タスクがプッシュされて実行されます。これまでのところすべて順調です。

公式ドキュメントで説明されているように、promise が即時かつ同期的に解決される上記の例に頭を悩ませることができます。new キーワードで promise を作成し、executor 関数を提供する場合も同じことが起こります。そのエグゼキューター関数は同期的に実行され、関数を解決します。したがって、 then が発生すると、解決された promise で非同期に実行できます。

console.log('start');

const p1 = new Promise(resolve => {
    console.log('promise 1 log');
    resolve('promise 1');
});

p1.then(msg => console.log(msg));

console.log('end');

上記のスニペットはstart, promise 1 log, end, promise 1、executor が同期的に実行されていることを証明する出力を出力します。

そして、これは約束と混同される場所です。次のコードがあるとしましょう:

console.log('start');

const p1 = new Promise(resolve => {
    console.log('promise 1 log');
    setTimeout(() => {
        resolve('promise 1');
    }, 0);
});

p1.then(msg => console.log(msg));

console.log('end');

これにより、 が発生しstart, promise 1 log, end, promise 1ます。エグゼキューター関数がすぐに実行される場合、その関数内の setTimeout が後で実行するためにタスク キューに置かれることを意味します。私の理解では、これは約束が現在も保留中であることを意味します。thenメソッドとその中のコールバックに到達します。これはジョブ キューに入れられます。残りの同期コードが実行され、空のコール スタックが作成されます。

私の理解では、約束のコールバックが優先されますが、まだ解決されていない約束でどのように実行できますか? promise は、その中の setTimeout が実行された後にのみ解決する必要がありますが、これはまだタスク キュー内にあります。追加の説明なしに、約束が解決された場合にのみ実行されると聞いたことがあります。私の出力から、それが真実であることがわかりますが、この場合にどのように機能するかわかりません。私が考えることができる唯一のことは、例外または類似のものと、マイクロタスクの前にタスクキュータスクが優先されることです。

これは長くなってしまったので、これを読んで答えてくれた人に感謝します。タスク キュー、ジョブ キュー、およびイベント ループをよりよく理解したいので、ためらわずに詳細な回答を投稿してください。前もって感謝します。

4

3 に答える 3