jQuery Deferred非同步回撥
在前端開發過程中,經常會遇到一些操作callback,需要在某一個操作condition之後執行,而某一個操作condition又是耗時的,為了滿足這樣的需求,常用的做法就是前置操作完成了,再呼叫callback回撥的方法。如下:
function callback(){ console.log("callback"); } function condition(){ setTimeout(function(){ callback(); },1000); } condition();
如果有些前置條件過多,會形成回撥地獄callback hell。
function condition(){ setTimeout(function(){ setTimeout(function(){ setTimeout(function(){ callback(); },1000); },1000) },1000); }
這種寫法很不優雅,程式碼可讀性也很差。這裡setTimeout()是模擬的一個非同步操作,在實際開發中可能是一個ajax請求。
關於非同步操作,在jQuery中,有解決辦法,可以很好的解決這類問題,就是Deferred非同步回撥,這裡需要結合promise,當前置條件執行完成了,就會觸發後續的操作。示例如下:
$(function(){ function d1(){ var dtd = $.Deferred(); console.log("d1 start"); setTimeout(function(){ console.log("1000 ms "); dtd.resolve(); },1000); return dtd.promise(); } function callback(){ console.log("callback..."); } $.when(d1()).done(function(){ callback(); }); });
這裡呼叫的結果如下所示:
通過jQuery的Deferred非同步,可以保證,callback在耗時操作d1()之後執行。jQuery中Deferred非同步寫法大致思路是這樣。
1、先申明一個dtd物件。var dtd = $.Deferred()
2、根據非同步操作執行的結果,分別觸發resolve(),reject()操作。
3、方法結束之前,返回dtd.promise()。
4、呼叫的時候,語法是$.when(d1()).done(callback()).fail(fail())。when中的條件就是我們的前置耗時操作,done中的函式是需要在前置條件之後執行的動作,如果前置條件執行出現異常reject()了,那麼會執行fail()中的操作。
本例中d1()方法中書寫了Deferred非同步程式碼,他可以直接執行,如:d1(),完全不受任何影響,也可以結合$.when().done()執行,作為前置條件,執行成功了,觸發後續操作。
這樣,整個的非同步就介紹完成了。思路也說明白了。
另外,這裡$.when()中只寫了一個前置條件,其實,$.when()可以傳入多個非同步操作,當所有的非同步操作都執行完成了,再執行done()裡面的操作。如下所示:
$(function(){
function d1(){
var dtd = $.Deferred();
console.log("d1 start");
setTimeout(function(){
console.log("1000 ms ");
dtd.resolve();
},1000);
return dtd.promise();
}
function d2(){
var dtd = $.Deferred();
console.log("d2 start");
setTimeout(function(){
console.log("2000 ms ");
dtd.resolve();
},2000);
return dtd.promise();
}
function d3(){
var dtd = $.Deferred();
console.log("d3 start");
setTimeout(function(){
console.log("3000 ms ");
dtd.resolve();
},3000);
return dtd.promise();
}
function callback(){
console.log("callback...");
}
$.when(d1(),d2(),d3()).done(function(){
callback();
});
});
執行結果如下:
d1 start
d2 start
d3 start
1000 ms
2000 ms
3000 ms
callback...
同樣的,可以保證callback在耗時操作d1,d2,d3均完成之後,才開始執行。