在前端这个领域里面,ajax请求非常常见,相信每一个前端er都写过下面的代码:
// 前提引入jquery
$.ajax({
type: 'get',
url: '/path/to/data',
success: function (response) {
},
error: function (errMsg) {
}
})
上面这段代码中的success和error被称为回调函数。基于js异步IO的特点,代码的意思就是在ajax请求成功之后,执行success函数,而在ajax失败时,执行error函数。
然而在有些情况下,业务逻辑可能需要我们产生多个success状态下的回调函数,或者多个ajax请求同时发送,全部success状态后执行回调,这样的方法就显得有些捉襟见肘。
1. 单次ajax请求有多个回调响应
// 使用上面的方法,有如下两种业务逻辑
$.ajax({
type: 'get',
url: '/path/to/data',
success: function (response) {
// todo
successCallback2(response);
successCallback3(response);
}
})
继续使用上面的写法,就会让回调进行嵌套,如果需要在successCallback2完成后继续回调,就要一层一层的嵌套。代码不是纵向发展,而是横向发展,这就是js中的回调地狱。
2. 多个ajax请求希望有一个共同的回调响应
// 继续使用最初的方法,假设有多个ajax请求,希望在全部完成后执行回调函数。
function fetchData (url, successCb, errorCb) {
return function () {
$.ajax({
type: 'get',
url: url,
success: successCb,
error: errorCb
});
}
}
function successCb () {
console.log('success');
}
function errorCb () {
console.log('error');
}
var fetchData1 = fetchData('/path/to/data1', successCb, errorCb);
var fetchData2 = fetchData('/path/to/data2', successCb, errorCb);
如果有两个相同的fetch data的操作,如果我们希望能够并行操作的话,只能重写fetchData1
var fetchData1 = fetchData('/path/to/data1', fetchData2, errorCb);
fetchData1();
这种写法实际上是在fetchData1成功后进行fetchData2操作的,并不是严格意义上的并行操作,之后在fetchData2的success状态的回调中,我们可以获得两次ajax请求的返回值。
这样的代码是不完美的,在如今大家都在追求webpack+es6+babel的技术栈时,也应该想想,如何从最基本的代码中提升生产力和代码的可维护性。
在发现了代码在业务中的痛点之后,就要想办法去解决它。好在如今前端百花齐放,这样的问题早已有多种成熟的解决方案,接下来的几篇文章,就由浅入深详细的讲讲这些异步方案中的实现方法和代码原理,并且每一种方法本人都实现了一个tiny版。所有文章代码都开源在github上,如果有任何问题或者建议甚至是错误,都可以在github中提issue给我。欢迎大家热烈讨论。
下一篇开始,着重介绍具体从Deferred对象解决上述两种问题,有兴趣的同学继续看下去吧。Javascript异步编程-延迟对象篇