JSタイマーsetTimeout非同期

7818 ワード

非同期参考文章
  • 関数呼び出しと関数の違い
  • //           
    
    function fn () { //  
        return 1;
    }
    
    fn(); //    
    console.log(fn); // ƒ fn() {return 1;}
    console.log(fn()); //1
    
    //                  return     
    function fn2 () {
        return function () {
            return 2;
        }
    }
    fn2//     
    fn2()//       function () { return 2; }
    fn2()(); //2
    
    タイマー
  • まず一つの例を見ます.
    function fn (){
        console.log(1);
    }
    setTimeout(fn);
    console.log(2);
    //       2 1,   2   1
    
    setTimeoutは、出力1のイベントを0秒後に設定します.ブラウザは、現在のコードを全部実行してから、setTimeoutのコードを後で実行します.
    function fn (){
        console.log(1);
    }
    var timeId = setTimeout(fn);
    console.log('id:' + timeId);//1
    console.log(2);
    timeId = setTimeout(fn);
    console.log('id:' + timeId);//2
    
    //     setTimeout      ,      setTimeout,           setTimeout   ,id     。
    
  • 間隔は、設定された時間よりも長くなります.
    function fn (){
        console.log(1);
        console.log(new Date()-0);
    }
    setTimeout(fn);
    console.log(new Date()-0);
    //         0,     date          ,             0,           , ‘   ’       setTimeout
    //           ,            
    
  • タイマーの「アイドリング」問題は、ブラウザがフォーカスを失うと、ユーザがブラウザに関心を持っていないとき、タイマーの出力が遅くなります.例えば、0.5秒を設定して一回実行すると、ブラウザを最小化してから1秒を経過することができます.
  • set Interval set Intevalについては、一つのtimerandだけであり、setTimeoutとは異なる
  • .
  • setTimeoutの関数の参照
  •     setTimeout(fn,500,1,2,3);
        function fn () {
            console.log(arguments); //[1,2,3]
        }
    
  • どうやってタイマーwindow.clearTimeoutをキャンセルしますか?
        var timerId = setTimeout('console.log("   clearTimeout,        ")',3000);
        window.clearTimeout(timerId); //     setTimeout  
        var timerId2 = setTimeout('console.log("   clearTimeout,      ")',3000);
    
    非同期とコールバック
    次の二つの例を見ると、非同期は結果を待たずに別のコードを実行して、あるコールバック関数に結果を知らせてくれます.
        function queue () {
            setTimeout(function () {
                return "     233";
            },60000); //60s        
        };
    
        var result = queue();
        console.log(result); //undefined   queue       return,      undefined                
    
    この場合、匿名関数の戻り値を取得するには、オブジェクトまたは関数を作成して、queueに入力します.queueの匿名関数はreturnをセットしなくてもいいです.設定しても取れないので、returnをセットしないで、直接にこの作成したプロキシ関数を値に取得して出力できます.
        function queue (agent) {  //  agent   
            setTimeout(function () {
                agent("     233"); //        return,      ,   agent       
            },3000); //60s        
        };
    
    //                   ,            ,  queue ,queue          return,         
    //         return,                ,     
        function agent (result) { //      
            console.log(result);
        }
        queue(agent); //        queue
    
    全体的な考えは、プログラムは次のように実行されます.プロキシ関数を作成して値を得て、setTimeoutの時間間隔が来たら値を取ってプログラムに戻ります.
    上記の例では、agent関数はコールバック関数である.全体をqueueに伝えて、queueを呼び出してからまた全体に伝えます.コールバック関数といいます.あなたに伝えます.呼び出してください.また送ってください.
    非同期とリピートはしばしば同時に現れます.非同期になっても後戻りしないということは、これをやめて結果を返すということになります.
    関連するいくつかの問題分析
    for (var i = 0; i < 5; i ++) {
        console.log(i); //0 1 2 3 4
    }
    
    
    for (var i = 0; i < 5; i ++) {
        setTimeout(function () {  //for     ,   setTimeout     i    5
            console.log(i);
        },1000*i);
    }
    
    第1回目の即時出力5は、第2回目が1000ミリ秒後に出力5回目が2000ミリ秒後に出力5を類推して5回目、jはsetTimeout内部の匿名関数を1秒ごとに印刷してiを出力したい場合、iが見つからない場合は、上のレベル、つまりグローバル中でiを探します.iはすでに5回目です.外部の時間間隔iはグローバルiと同じものです.毎回の値は0,1,2,3,4です.
    for (var i = 0; i < 5; i ++) {
        (function () {
            setTimeout(function () {
                console.log(i);
            },i * 1000);
        })(i);
    }
    
    第二の問題の結果と同様に、1000乗iのそのiは全体の中のiで、毎回0,1,2,3,4です.
    setTimeoutの中の関数の作用域に出力するiは存在しません.前の段階の作用域に行くとすぐに関数の中からiを探します.直ちに実行関数の中にもiがありません.また、グローバルスコープの中でiを探すと、forサイクルはもう終わりました.iは5です.だから、毎回5を出力します.
    for (var i = 0; i < 5; i ++) {
        (function (i) {
            setTimeout(function () {
                console.log(i);
            },i * 1000);
        })(i);
    }
    
    3番と違って、ここですぐに実行関数が形参を書きました.この形は変数宣言var i=argments[0]に相当します.
    setTimeoutの中の関数はiを出力する時、iが見つけられなくて、一級上の作用域に着いたらすぐに関数を実行して探します.3番と違って、今回の直ちに実行関数の中にiがあります.もう大域作用領域にiを探すことはできません.
    形参と書くとiが定義されているので、このとき出力されるiは即時実行関数のiであり、このiが入ってきた値は当時の大域のiの値0,1,2,3,4である.
    for (var i = 0; i < 5; i ++) {
        setTimeout((function (i) {
            console.log(i);
        })(i),i * 1000)
    }
    
    第5の問題は依然として作用ドメインチェーンによって理解されています.setTimeoutの中の関数の役割領域で出力されるiは、直ちに関数のiを実行します.これは、形参を定義しています.この形参は毎回受信するiは当時の大域のiの値0,1,2,3,4です.時間間隔のiはグローバルのiです.毎回の値は0,1,2,3,4です.結果を求めてから、第5問に対して、コードを簡単にして、詳しく分析してみます.
        for (var i = 0; i < 5; i ++) {
            var t1 = function (i) {
                console.log(i);
            };
            var t2 = t1(i);
            setTimeout(t2,1000*i);
        }
    
    
    コードを分解してから分析します.この時set Timeoutの中で実行されるのはt 2で、t 2はt 1呼び出しの結果、t 1にはreturnが書いていません.デフォルトはundefinedに戻ります.だからt 2はundefinedです.
        setTimeout(undefined,0);
        setTimeout(undefined,1000);
        setTimeout(undefined,2000);
        setTimeout(undefined,3000);
        setTimeout(undefined,4000);
    
    出力の値は、t 1のconsone.log(i)である.私達もはっきりと見ることができます.このiは伝来の当時の毎回のi値0,1,2,3,4です.
    set Timeoutの応用:逆タイマーを作る Document var show = document.querySelector('#show'); var start = document.querySelector('#start'); var pause = document.querySelector('#pause'); var resume = document.querySelector('#resume'); var select = document.querySelector('#mySelect'); // var timeLeft; // function showtime () { // show.innerText = timeLeft + ' '; // timeLeft -= 1; // if (timeLeft === 0) { // return; // } // setTimeout(showtime,1000); // } // start.addEventListener('click',function () { // var seconds = 60 * parseInt(select.value); // timeLeft = seconds; // showtime(); // }); // bug, start , setTimeout // , start , setTimeout , setTimeout , timerId var timeLeft; var lastTimerId; // lastTinmerId function showtime () { show.innerText = timeLeft + ' '; timeLeft -= 1; if (timeLeft === 0) { return; } lastTimerId = setTimeout(showtime,1000); // seTimeout timerId } start.addEventListener('click',function () { var seconds = 60 * parseInt(select.value); timeLeft = seconds; // setTimeout if (lastTimerId !== undefined) { window.clearTimeout(lastTimerId); } showtime(); pause.disabled = false; // start pause }); // // , timeLeft, timeLeft pause.addEventListener('click',function () { if (lastTimerId) { window.clearTimeout(lastTimerId); } resume.disabled = false; // pause resume pause.disabled = true; // pause pause }) resume.addEventListener('click',function () { showtime(); // , showTime() timeLeft , timeLeft pause.disabled = false; // resume pause resume.disabled = true; // resume , resume })