JavaScript非同步編程的方法

來源:互聯網
上載者:User

標籤:非同步任務   publish   font   邏輯   ted   pos   請求   span   訊號   

非同步編程

在瀏覽器端,非同步編程非常重要,耗時很長的操作都應該非同步執行,避免瀏覽器失去響應。最常見的例子就是通過AJAX向伺服器發送非同步請求。

非同步編程有很多種方法

1、回呼函數

比如有兩個函數
f1();
f2();//f2依賴於f1的執行狀態
如果f1耗時很長,它會阻塞後面程式的運行
我們利用setTimeout來改寫f1,因為setTimeout是非同步

function f1(callback){    setTimeout(function(){        //f1的代碼,耗時很長,這裡是又開啟了一個線程,        callback();//f1完後執行callback()    },1000)}f1(f2);//這段代碼不會阻塞後面的程式運行,f2依賴於f1的執行狀態

採用這種方式,我們把同步操作變成了非同步作業,f1不會堵塞程式運行,相當於先執行程式的主要邏輯,將耗時的操作延遲執行。
這種方法很簡單,也容易理解,但是不利於代碼的閱讀和維護,各個部分之間高度耦合,而且每個任務只能指定一個回呼函數

2、事件監聽
另一種思路是採用事件驅動模式。任務的執行不取決於代碼的順序,而取決於某個事件是否發生。

f1.on(‘done‘,f2);//為f1綁定一個事件(f2訂閱事件)function f1(){    setTimeout(function(){        //f1的代碼        f1.trigger(‘done‘);//f1觸發這個事件(f1發布事件)    },1000)}

這種方法可以綁定多個事件,每個事件可以指定多個回呼函數,而且可以"去耦合"有利於實現模組化。
缺點是整個程式都要變成事件驅動型,運行流程會變得很不清晰。

3.發布訂閱模式
又稱觀察者模式,它廣泛的應用於非同步編程中,是一種代替回呼函數的方案。
上面講到的事件,可以理解成“訊號”
假定,存在一個"訊號中心",某個任務執行完成,就向訊號中心"發布"一個訊號,其他任務可以向訊號中心"訂閱"這個訊號,從而知道什麼時候自己可以開始執行。
這就叫做"發布/訂閱模式",又稱"觀察者模式"
發布訂閱者模式可以去除對象之間的耦合,有利於實現模組化,而且我們可以通過查看"訊息中心",瞭解存在多少訊號、每個訊號有多少訂閱者,從而監控程式的運行。

這個模式有多種實現,下面採用的是jQuery的一個外掛程式。

//f2向"訊號中心"jQuery訂閱"done"訊號jQuery.subscribe("done", f2);function f1(){    setTimeout(function () {      // f1的任務代碼      jQuery.publish("done");//f1執行完成後,向"訊號中心"jQuery發布"done"訊號,從而引發f2的執行。    }, 1000);  }

4.Promise對象
Promises對象是CommonJS工作群組提出的一種規範,目的是為非同步編程提供統一介面,使得控制非同步作業更加的容易
ES6將Promsie納入了規範,並原生提供了Promise對象
簡單說,它的思想是,每一個非同步任務返回一個Promise對象,該對象有一個then方法,允許指定回呼函數。比如,f1的回呼函數f2,可以寫成:
f1().then(f2);
promise優點在於避免層層嵌套的回呼函數,回呼函數變成了鏈式寫法,程式的流程可以看得很清楚,並且提供了統一的介面,使得控制非同步作業更加的容易。
而且,它還有一個前面三種方法都沒有的好處:如果一個任務已經完成,再添加回呼函數,該回呼函數會立即執行。所以,你不用擔心是否錯過了某個事件或訊號。
這種方法的缺點就是編寫和理解,都相對比較難。

例子:我們用promise對象實現AJAX操作

var getJSON=function(url){    var promise=new Promise(function(resolve,reject){        //AJAX操作        $.ajax({            url:url,            type:‘GET‘,            dataType:‘json‘,            success:function(data,status,xhr){                resolve(data);            },            error:function(xhr,textStatus){                reject(textStatus);            }        })    })    return promise;}
getJSON(‘/post.json‘)    //任務Resolve狀態的回呼函數,返回是這個promise對象    .then(function(value) {        console.log(value);    })    //任務Rejected狀態的回呼函數    .catch(function(error){        console.log(error);    })

採用鏈式的then方法可以指定按照次序調用的回呼函數
如果前一個回呼函數返回的是另外一個promise對象,那麼後一個回呼函數就會等待該promise對象狀態發生變化再調用

getJSON("url1")    .then(function(value){         return getJSON(value.url2);//返回另外一個promise對象     })     //另外一個promise對象Resolve狀態的回呼函數    .then(function(value){        console.log(value)    })

 

JavaScript非同步編程的方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.