在前端开发过程中,经常会遇到一些操作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均完成之后,才开始执行。