JavaScript同期、非同期、フィードバックの実行順序の経典setTimeout面接問題分析
2819 ワード
コツを破る:同期優先、非同期クッション、バッククッション
次にコードを入れて、この出力の過程をよく見ます.
1.同期コードを見る:a変数はPromiseで、Promiseが非同期であることを知っています.彼のthen()とcatch()の方法を指しています.Promise自体は同期です.ここで先にa変数内部のPromise同期コードを実行します.(同期優先)2、Promise内部には4つのconsoneがあり、2番目は一つのsetTimeoutコールコールバックです.ここでまず1、3、4コールの出力方法をメッセージ列に捨てて待ちます.3、次にresoveを実行して、thenに入ります.thenは非同期で、まだ同期が終わっていません.だから、thenもメッセージの列に並んで待ちます.4、b変数も一つのPromiseです.aと同じように、内部の同期コードを実行して、5を出力して、set Timeoutはメッセージの列に行って待ちます.5、一番下の同期出力7.6、同期コードの実行が完了したら、JavaScriptはメッセージキューに向かって非同期のコードを呼び出します.非同期は実行に出てきました.ここには非同期thenが一つしかないので、出力は8です.7、非同期もover.折り返しの子供たち:折り返し、出てきました.ここには2回の順番があります.彼らの時間は全部0に設定されていますので、時間の影響を受けずに、並んでいる順番と関係があります.まずaの中のコールバック2を出力して、最後にbの中のコールバック6を出力します.(ここで時間が違ったら、実行順は時間順に出力します)8、最終的な出力結果は、1、3、4、5、7、8、2、6です.
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log('i--- ',i);
}, 1000);
}
console.log(i);
//
5
i--- 5
i--- 5
i--- 5
i--- 5
i--- 5
なぜ出力はこうですか?以下では、1、forサイクルと循環外のsolieが同期していることを分析しますので、forサイクルを先に実行して、外部のsolie.logを実行します.(同期優先)2、forサイクルの中にsetTimeoutフィードバックがあります.彼は下地の存在です.最後に実行するしかないです.(バッククッション)分析:forサイクルは先に実行しますが、setTimeoutに転送しないで、forサイクルが終わったら、setTimeoutに転送します.外部のsolieは5を印刷します.forサイクルが完了したからです.内部のsetTimeoutフィードバック実行時にはforサイクルが既に実行されていますので、このときi=5はsetTimeoutに転送されます(5)ので、setTimeout内部のsolone.log出力は5です.次にコードを入れて、この出力の過程をよく見ます.
for (var i = 0; i < 5; ++i) {
setTimeout(function() {
console.log('s---',i);
}, 1000);
console.log('c---', i); //
}
console.log(i);
//
c--- 0
c--- 1
c--- 2
c--- 3
c--- 4
5 //console.log(i);
s--- 5
s--- 5
s--- 5
s--- 5
s--- 5
この時面接官はあなたにどうやって0、1、2、3、4を正常に出力できますか?二つの方法を以下に示します. :
for (let i = 0; i < 5; ++i) {
setTimeout(function() {
console.log('s--- ',i);
}, 1000);
}
console.log(i);
//
i is not defined
s--- 0
s--- 1
s--- 2
s--- 3
s--- 4
分析:私たちは、変数iの定義としてletを使った後、forループを実行するたびに、まずsetTimeoutにフィードバックします.正確にはloopに参加し、loopにはクローズドパケットが形成されています.このように5 loopを実行しました.各loopパスのパラメータはそれぞれ0、1、2、3、4の後にloopの中のsetsout Timeoutがキューに入るということです.外部のconsolieが実行されたら、forサイクルの中のiは新しい変数になります.iですので、外部にあるconsoli.log(i)は存在しません. :
var loop = function (_i) {
setTimeout(function() {
console.log('2:', _i);
}, 1000);
};
for (var _i = 0; _i < 5; _i++) {
loop(_i);
}
console.log(i);
上では同期とコールバックの実行手順について説明しましたが、次に同期、非同期、コールバックを含む例を挙げます.let a = new Promise(
function(resolve, reject) {
console.log(1)
setTimeout(() => console.log(2), 0)
console.log(3)
console.log(4)
resolve(true)
}
)
a.then(v => {
console.log(8)
})
let b = new Promise(
function() {
console.log(5)
setTimeout(() => console.log(6), 0)
}
)
console.log(7)
コツの一番重要な思い出(同期-非同期-リフレクト)を分析します.1.同期コードを見る:a変数はPromiseで、Promiseが非同期であることを知っています.彼のthen()とcatch()の方法を指しています.Promise自体は同期です.ここで先にa変数内部のPromise同期コードを実行します.(同期優先)2、Promise内部には4つのconsoneがあり、2番目は一つのsetTimeoutコールコールバックです.ここでまず1、3、4コールの出力方法をメッセージ列に捨てて待ちます.3、次にresoveを実行して、thenに入ります.thenは非同期で、まだ同期が終わっていません.だから、thenもメッセージの列に並んで待ちます.4、b変数も一つのPromiseです.aと同じように、内部の同期コードを実行して、5を出力して、set Timeoutはメッセージの列に行って待ちます.5、一番下の同期出力7.6、同期コードの実行が完了したら、JavaScriptはメッセージキューに向かって非同期のコードを呼び出します.非同期は実行に出てきました.ここには非同期thenが一つしかないので、出力は8です.7、非同期もover.折り返しの子供たち:折り返し、出てきました.ここには2回の順番があります.彼らの時間は全部0に設定されていますので、時間の影響を受けずに、並んでいる順番と関係があります.まずaの中のコールバック2を出力して、最後にbの中のコールバック6を出力します.(ここで時間が違ったら、実行順は時間順に出力します)8、最終的な出力結果は、1、3、4、5、7、8、2、6です.