javascript的單線程異步機制探究

JavaScript的同步異步模式

JavaScript的語言執行環境都是單線程。單線程就是想排隊那樣任務須要按順序一個一個的完成。這種模式的好處是實現起來簡單,可是壞處就是若是隊列中有一個任務耗費時間很長,那後邊的任務就必須等前一個執行完,會拖延整個程序的執行。javascript

爲了優化這個問題,JavaScript語言將任務的執行模式分紅兩種,同步(Synchronous)和異步(Asynchronous)。html

同步模式就是後一個任務等待前一個任務結束,而後再執行,程序的執行順序與任務的排列順序是一致的、同步的。java

異步模式則徹底不一樣,每一個任務有一個或者多個回調函數,前一個任務結束後,不是執行後一個任務,而是執行回調函數,後一個任務不須要等前一個任務執行完才執行,程序的執行順序與任務的執行順序是不一致的。在瀏覽器端,耗時很長的操做都應該異步執行,避免瀏覽器失去響應。編程

那異步模式又有幾種實現方式呢,promise

異步模式有四種實現方式,回調函數方式,事件監聽方式,發佈-訂閱方式和Promise方式

1,回調函數

回調函數就是將函數做爲參數傳到須要回調的函數內部再執行,例如f1很耗時,f2須要f1的執行結果才能執行,f3不須要f1,f2的結果,須要儘快執行,瀏覽器

那咱們就嘗試用異步,將f2做爲參數傳到f1的回調函數內部。代碼以下,異步

function f1(func){

        var tip = '';

        setTimeout(function(){

            for(var i = 0;i <= 10000;i++){

                if(i == 10000){

                    tip = 'f1執行完,f2須要我'

                }

                console.log(i);

            }

            func(tip);

        },0);

    }

    function f2(tip){

        console.log(tip);

    }

    function f3(){

        console.log("f3執行");

    }

    f1(f2);

    f3();

這個異步是實現其實主要是靠setTimeout實現的,這個函數將要執行的函數放到隊列最後邊也就是f3的後邊,因此f3執行完纔會執行for循環和f2,js是單線程的,因此異步的實現其實就是將耗時的放到最後邊,當任務進程裏面的任務執行完以後再去執行後邊添加的任務。async

2,事件監聽

這個思路是採用事件驅動模式。任務的執行不取決於代碼的順序,而是取決於某個事件是否發生。這種模式跟綁定事件的機制實際上是同樣的,例如給某個DOM元素綁定click事件,當click觸發的時候纔會執行綁定的函數,那咱們如今模擬一個done事件,這裏用jQuery的寫法。爲f1綁定一個done事件,當f1發生done事件,就執行f2。異步編程

f1.on('done', f2);

function f1(){

setTimeout(function () {

// f1的任務代碼

f1.trigger('done');

}, 0);

}

f1.trigger('done')表示,執行完成後,當即觸發done事件,從而開始執行f2。函數

這種方式與回調函數的區別就是取決於某個事件是否發生來執行異步的,最終實現也是setTimeout實現的。

3,訂閱/發佈

這個跟事件監聽的區別是信號監聽,假設有個信號中心,某個任務完成,就像信號中心發個信號,其餘任務能夠向信號中心訂閱這個信號,從而知道本身何時能夠執行。

Event.subscribe("done", f2);

function f1(){

setTimeout(function () {

// f1的任務代碼

Event.publish("done");

}, 1000);

}

f2向信號中心訂閱done信號,

Event.publish("done"); 這句意思是當f1執行完,向信號中心發佈done,f2接收到信號,開始執行。

4,promise對象是CommonJS工做組提出的一種規範,目的是爲異步編程提供統一接口。promise是ECMAScript 6規範內定義的.

Promise是一個對象,它的構造函數接收一個回調函數,這個回調函數參數有兩個函數:分別在成功狀態下執行和失敗狀態下執行,Promise有三個狀態,分別爲:等待態(Pending)、執行態(Fulfilled)和拒絕態(Rejected)。

    

var promise = new Promise(function(resolve, reject) {

  if (/* 異步操做成功 */){

    resolve(value);

  } else {

    reject(error);

  }

});

promise.then(function(value) {

  // success

}, function(value) {

  // failure

});

上面代碼表示,Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolve方法和reject方法。若是異步操做成功,則用resolve方法將Promise對象的狀態變爲「成功」(即從pending變爲resolved);若是異步操做失敗,則用reject方法將狀態變爲「失敗」(即從pending變爲rejected)。

then()方法是Promise對象的核心,它返回一個新的Promise對象,所以能夠像jQuery同樣鏈式操做.

這只是初步對promise的瞭解,它屬於ES6新加的對象,Promise/Deferred異步模型蘊含的編程思想是咱們更應該瞭解的。

參考博客:

JavaScript異步編程原理

JavaScript下的setTimeout(fn,0)意味着什麼?

Javascript異步編程的4種方法 

相關文章
相關標籤/搜索