ブラウザの非同期メカニズムの初歩的な概要

3902 ワード

まずJavaScript非同期の概念を述べます:まずjsは単一スレッドの言語であり、非同期の特性がないからです.
そしてjsのホスト環境はブラウザ側で、jsの非同期操作はブラウザが提供して、ブラウザのjsエンジンはjsコードを実行する時もただ1本のスレッドを提供して実行するだけで、本当にけちです...そして!js(メインスタック列内のjs、後述するメインスタック列とは何か)コード実行は、レンダリングスレッドとブラウザイベントトリガスレッドをブロックします.後の2つのスレッドはブラウザ内の常駐スレッドに属しています.もちろんhttpリクエストスレッドなどもあります.例えば、jsコード内にDOM要素のスタイルを変更するコードがあります.実行した後は、このレンダリングイベントを記録するだけです.レンダースレッドを切り替えてレンダーするのではなく、残りのメインスタック列のコードを実行し続けます.煩わしいです.また、メインスタック列とタスクキューの概念を解析します.チェン一峰のevent loop解析を見に行くことができます.つまり、コードを計算しましょう.
$.ajax({   
type:'get',   
url:url,  
beforeSend:function() {
      console.log('     ,    ajax ,         ')         
   },  
success:function(data){      
      console.log('ajax    ,  setTimeout        ')            
   },  
})
setTimeout(function() {   
console.log('      ')
},0)
console.log('     ,    ')
//    
1.     ,    ajax ,         
2.     ,    
3.jquery-1.9.1.min.js:5 XHR finished loading: GET "http://localhost:2000/123".
4.ajax    
5.      

jsエンジンがjsコードを解析するとき、settimeoutとsetIntervalまたはajaxに遭遇すると、ゆっくりと教えてくれます.あなたたちの先進的なタスクキューの中など、私はメインスタックの列に残っているコードを実行します.
その後、メインスタック列のコードを実行した後、jsスレッドが完了した後、すぐにタスクキュー内にタスクを探してメインスタック列に置くのではなく、レンダリングエンジンが必要かどうかを確認します.例えば、DOM要素の背景色を変更すると、ある場合はレンダリングスレッドを切り替えて、まずページのレンダリングに必要なrepaintとreflowを作ります.repaintとreflowについてはここでは述べませんが、googleに興味があるでしょう.
それはレンダリングエンジンにレンダリングの仕事を終えさせて、ブラウザはやっと帰ってタスクキューに人が書留しているかどうかを探して、ポーリングのメカニズムを取って、医者と患者を見るのはそんなに悪くありません.つまり、ajaxはsettimeoutとsetIntervalより優先度が高いと言って、ajaxイベント1を実行した後、タスクキューを見に帰りますか?nonono、まずレンダリングエンジンがしなければならないことがあるかどうかを見て、つまりもう一度メインスタック列の流れを歩いて、レンダリングしていないことですか?では、次の患者にしましょう.
テーマに戻る...なぜ非同期が必要なのか、前に述べたjsブロックのため、ajaxが同期して実行されているとしたら.では、サーバーが私の要求に応答して、データを手に入れてから他のことをします.もしサーバーが要求できないなら、それはlowではありませんか.ブラウザが何をしたのかはajaxに着いたとき、それをタスクキューに押す前に、httpスレッドを起こして、要求を送信します.要求が完了しました.ajaxイベントがタスクキューの末端に押されて、非同期を実現します.上で述べたように、settimeoutとsettIntervalは予想されるイベントよりも少し多いです.キューでは、すぐに実行するのではなく、明日更新します.
では、乾物が来ました.日常の書く(lu)作(ma)の中で、私たちはどのように非同期メカニズムを利用して私たちが望んでいる非同期操作を完成させるべきですか.
(一)welcome to callback hell(コールバック関数)
function getSomething(fn){
   var num=0;
   settimeout(function(){
       num=1;
       fn(num);
   })
}
function compute(x) {
   alert(x * 2);
}
getSomething(compute);//  ,         

前述したようにsettimeout内のjsコードはすべてメインスタック列に入ると、実行順序は上から下になるが、複雑な需要の下でこの方法はcallback hellを生成し、詳細な非同期ステップを容易に見ることができず、簡単な論理では使用できない.
(二)promise
function getSomething() { 
    var r = 0; 
    return new Promise(function(resolve) { 
        setTimeout(function() { 
            r = 2; 
            resolve(r); 
        }, 10); 
    });}
function compute(x) { 
    alert(x * 2);
}
getSomething().then(compute);
//    Promise        Promise   ,          ...         

(三)generator
function getSomething() {   
    var r = 0;   
    setTimeout(function() {      
        r = 2;      
        it.next(r);   
    }, 10);
}
function *compute(it) {   
    var x = yield getSomething();   
    alert(x * 2);
}
var it = compute();
it.next();
//      demo......      es6   

(四)promise+generator
function getSomething() {   
    var r = 0;   
    return new Promise(function(resolve) {      
    setTimeout(function() {         
        r = 2;         
        resolve(r);      
    }, 10);   
 });
}
function *compute() {   
    var x = yield getSomething();   
    alert(x * 2);
}
var it = compute();it.next().value.then(function(value) {   
    it.next(value);
});

(五)async(ES 6は飽きたが、ES 7はまだ遠いのか、非同期操作の究極の大法)
function getSomething() { 
    var r = 0; 
    return new Promise(function(resolve) { 
        setTimeout(function() { 
        r = 2; 
        resolve(r); 
    }, 10); 
});}
async function compute() { 
    var x = await getSomething(); 
    alert(x * 2);
}
compute();

眠死本宝宝宝..1時です.
おやすみなさい