JavaScript同期、非同期、フィードバックの実行順序の経典setTimeout面接問題分析

2819 ワード

コツを破る:同期優先、非同期クッション、バッククッション
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です.