1. 程式人生 > >jQuery Deferred非同步回撥

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均完成之後,才開始執行。