在前面,有一篇文章介绍了jQuery的异步对象Deferred,通过他,我们可以实现一些操作比如回调函数在异步操作(耗时)完成之后再执行。比如这样的场景,我们在编辑页面,对一个产品对象进行编辑,而该对象一些属性比如所属渠道,是可以下拉选择,而所属渠道不是固定不变的,而是根据后台接口channel/getAll返回给前台页面。这时候,我们需要先初始加载渠道这个下拉框,然后根据产品自己的属性值的渠道来反显渠道initForm()。这是一个很常见的场景。如果在渠道下拉框没有初始化完成之前,产品渠道先反显了,那么很有可能最后又初始化渠道下拉框的时候,将这个反显的值冲掉了。
让一个操作在另一操作之后执行,我们可以使用嵌套的方式,让一个异步接着另一个异步,这样虽然可以解决问题,但是却造成了另外一个callback hell的问题。代码可读性差。
为此,我们需要用到异步对象来让完成这个操作。
function getAll(){
var dtd = $.Deferred();
$.ajax({
url:"channel/getAll",
success:function(){xxx;dtd.resolve();xxx}
});
return dtd.promise();
}
function initForm(){xxx;}
$.when(getAll()).done(initForm);
这样,就解决了我们的问题,初始化表单会在初始化渠道getAll()方法完成之后进行。
在实际的场景中,还有可能有这样的需求,几个耗时操作,需要按照顺序执行。我们知道$.when()方法,可以运行多个耗时的异步操作[d1,d1,d3],但是这些耗时操作是同时执行的,只有done()里面的方法会在这些异步操作[d1,d2,d3]都执