イベントには、理解するために秒ループ
簡単な紹介
JSは、シングルスレッド理由になるように設計シングルスレッドのスクリプト言語ですか?
例えば、スレッドがDOMを変更し、JSはマルチスレッドのスクリプト言語であると仮定し、Bのスレッドは、最初のスレッドBの実行が完了したら、DOMが削除され、スレッドがこのような回避問題にするために、与えられている、JSは、DOMを削除しましたシングルスレッド化のために設計されました
質問は、単一のスレッドが一つだけ、行うための第二のことを行うことができ、事前に行うことがまず最初になるようです。更新されたデータのための需要がある場合は5分ごとに、たsetInterval行く時間が、このページのJSは、他のことを行うことができませんので、スレッドはのsetIntervalで占有されています。JSは、同時に複数のタスクを実行することができようにするには、イベントループの導入(イベントループ)メカニズム
イベントループは、キュー、タスクキュー、マイクロタスクキューの2種類に分けられ、業界は一般的に、マクロタスクキュータスクと呼ばれ、マイクロタスクと呼ばれるマイクロタスクを翻訳しました。
タスクキューおよびキューマイクロタスクの実行順序は何ですか?
コードの実装を開始すると、全体としてのコードは、実装工程で、すぐにタスクを実行するタスクであります
- エンカウンターのsetTimeout、のsetInterval、I / O、setImmediate(Nodejs環境)はタスクキューのプッシュに出て行きます
- 出会いPromise.then /キャッチ/最後に、MutationObserver、process.nextTick(Nodejs環境)は、キュープッシュマイクロタスクに出て行きます
各タスクを実行した後、キューはマイクロタスクが実行すべきタスクが存在しないでしょう、そうであれば、FIFO原理は、タスクの実行に続いて押して、バック終了タスク実行キューに、実行するタスクを削除し、もしいいえ、直接次のタスクへ、というように、これは再帰的な実装プロセスと同様イベントループは、あります
ケース
上記の規則によると、次のコードの出力シーケンスを考えます
// 先自己思考一下输出顺序
console.log('script start');
setTimeout(function () {
console.log('timeout');
}, 0);
Promise.resolve().then(function () {
console.log('promise');
}).then(function () {
console.log('then');
});
console.log('script end');
分析:
- 全体的に最初のタスクとしてのコードは、上から下に開始します
- 輸出
script start
- 出会い
setTimeout()
、実行されるのを待って、タスクキューにプッシュ - 遭遇した
Promise
最初のthen()
、実行されるのを待って、マイクロタスクキューにプッシュ - 輸出
script end
- 最初のタスクの実行が完了すると、ビューのマイクロタスクキューは、実行を開始するタスクを持っています
- 出力
promise
、第二の面then()
、マイクロタスクのキューのプッシュ - ただ、出力をプッシュ
then
- マイクロタスクキューの実行は、タスクの実行削除を完了しています
- 輸出
timeout
出力順:スクリプト開始 - >スクリプトの終わり - >約束 - >そして - >タイムアウト
アップグレード、約束を返します
上記の例の約束は、内部Promise.then約束、どのように分析があると仮定して、アップグレード?
Promise.resolve().then(function () {
console.log('promise');
return new Promise((resolve, reject) => {
console.log('inner promise');
resolve();
}).then(() => {
console.log('inner then1');
}).then(() => {
console.log('inner then2');
})
}).then(function () {
console.log('then');
});
分析:
- 全体的に最初のタスクのためのコードは、上から下に開始します
- その後、最初の出会いは、マイクロタスクにキューをプッシュします
- 最初のタスクの実行が完了すると、ビューのマイクロタスクキューは、実行を開始するタスクを持っています
- 輸出
promise
- 新しい約束を入力、出力
inner promise
- その後、最初の内部に新しい約束、プッシュキューマイクロタスクに遭遇
- ただ、出力をプッシュ
inner then1
- 内部新たな約束は、第二、次に遭遇した、マイクロタスクにキューをプッシュします
- ただ、出力をプッシュ
inner then2
- 内部の新しい約束は、その後、第一の外部の約束の戻り値を取得するマイクロタスクに、その第二の面、キューのプッシュをダウン継続実行しました
- ただ、出力をプッシュ
then
出力順:約束 - >インナー約束 - >インナーthen1 - >インナーthen2 - >その後、
注:その後、連鎖呼び出しは、従来の方法は、次に、変更後の新たなプロミスオブジェクト状態を待機当時、新しい約束するオブジェクトを返す場合、両者の実行により、換言すれば、実装されるときに非同期になります同期させるために、リターンはそれを取り除きますか?
変更、ノーリターンの約束
Promise.resolve().then(function () {
console.log('promise');
new Promise((resolve, reject) => {
console.log('inner promise');
resolve();
}).then(() => {
console.log('inner then1');
}).then(() => {
console.log('inner then2');
})
}).then(function () {
console.log('then');
});
分析:
- 全体的に最初のタスクのためのコードは、上から下に開始します
- その後、最初の出会いは、マイクロタスクにキューをプッシュします
- 最初のタスクの実行が完了すると、ビューのマイクロタスクキューは、実行を開始するタスクを持っています
- 輸出
promise
- 新しい約束を入力、出力
inner promise
- 上記第6工程と同様に、まず内部新しい約束、マイクロタスクキューへプッシュ遭遇
- この場合、外部オブジェクトで最初の同期コードは、マイクロタスクのキュープッシュ、次いでその第二を行い、プロミスにわたって行われてきました
- マイクロタスクを続行し、出力
inner then1
- その後、2番目の新しい約束の内部に、キューマイクロタスクをプッシュ
- マイクロタスクを続行し、出力
then
- 最終的な出力
inner then2
出力順:約束 - >インナー約束 - >インナーthen1 - >そして - >インナーthen2
要約:リターンを除去した後、次いで次にジャンプする同期コードの前に実行され
考えます
最後に、問題について考え、次のエラーがそれをキャッチするために捕獲することができますか?なぜ?
new Promise(function (resolve, reject) {
setTimeout(function () {
throw new Error('test')
}, 0)
resolve('ok');
}).catch(err => {
console.error(err);
});
イベントループに精通し、この質問に答えるのは簡単です:キャプチャすることはできません。そのため内部のsetTimeoutは、スローのsetTimeoutと間違った時間を投げ、同じタスクを実行していない.catchでのエラーのため、漁獲量が引き継がれました。
私は、スターポイント、それは良い感じのGithubを