Open YIXUNFE opened 8 years ago
最近有一些项目,是从已有的功能上新增一些数据,比如个人账户中新增一些数据。后端并没有在原有接口上提供所需数据,而是希望我们调用另一个接口,这个接口仅仅提供新增的数据。
由于新接口和旧接口在数据上并没有依赖关系,所以我们可以等两个接口都请求完成后将数据填充到 DOM 结构中。在这个问题的解决过程中就出现了一些不太简洁的代码,比如:
var len = 2, data = {} cb = function () {...} //一个请求 $.ajax({ url: url1, ... }).then(function (d) { len-- $.extend(data, d) if (len === 0) { cb(data) } }) //又一个请求 $.ajax({ url: url2, ... }).then(function (d) { len-- $.extend(data, d) if (len === 0) { cb(data) } })
这种解决方案虽然能处理当前项目中的实际问题,但是当这类无序的异步请求是 N 个的时候,这种方法就有点捉襟见肘了。而利用 jQuery.when 方法,即能很好的解决这些问题,而且能够使代码简洁优雅易于维护。
$.when($.ajax({ url: url1, ... }), $.ajax({ url: url2, ... })).done(function (data1, data2) {...}).fail(function () {...})
简洁明了了许多吧:smile:
上面提到将多个异步请求作为参数传入 jQuery.when 方法中,这个描述并不正确,因为 jQuery.when 接受的是延迟对象(jQuery.Deferred),巧在 jQuery.ajax 方法返回的 jqXHR 对象(浏览器原生 XHR 对象的超集)就是一个延迟对象(jQuery 1.5+),所以看上去我们是将 jqXHR 对象作为了参数,这确实让人产生了一定的误解。
在处理普通的延迟问题的时候,我们就需要在异步方法中明确地返回延迟对象。
var dfd1 = new $.Deferred(), dfd2 = new $.Deferred() function wait1 (dfd) { setTimeout(function () { dfd.resolve('wait1 done') }, 1000) return dfd.promise() } function wait2 (dfd) { setTimeout(function () { dfd.resolve('wait2 done') }, 2000) return dfd.promise() } $.when(wait1(dfd1), wait2(dfd2)).done(function (data1, data2) { console.log(data1) // 'wait1 done' console.log(data2) // 'wait2 done' })
jQuery.when 方法返回的是一个 Promise 对象(延迟对象的一个子集),可以调用它的 done、fail、then 方法执行回调函数。这里列一下这些方法中回调函数的执行条件。
done
fail
then
另外需要注意的是,当 jQUery.when 方法被传入了一个以上的参数时,回调函数中的参数可能是一个数组。因为在传递给一个延迟对象的解决(resolved)事件为多个值的情况下,相应的参数将是这些值组成的数组。
var dfd1 = new $.Deferred(), dfd2 = new $.Deferred() function wait1 (dfd) { setTimeout(function () { dfd.resolve('wait1', 'done') }, 1000) return dfd.promise() } function wait2 (dfd) { setTimeout(function () { dfd.resolve('wait2', 'done') }, 2000) return dfd.promise() } $.when(wait1(dfd1), wait2(dfd2)).done(function (data1, data2) { console.log(data1) // ['wait1', 'done'] console.log(data2) // ['wait2', 'done'] })
jQuery.ajax API 传送门 jQuery.when API 传送门
利用 jQuery.when 简化代码
最近有一些项目,是从已有的功能上新增一些数据,比如个人账户中新增一些数据。后端并没有在原有接口上提供所需数据,而是希望我们调用另一个接口,这个接口仅仅提供新增的数据。
由于新接口和旧接口在数据上并没有依赖关系,所以我们可以等两个接口都请求完成后将数据填充到 DOM 结构中。在这个问题的解决过程中就出现了一些不太简洁的代码,比如:
这种解决方案虽然能处理当前项目中的实际问题,但是当这类无序的异步请求是 N 个的时候,这种方法就有点捉襟见肘了。而利用 jQuery.when 方法,即能很好的解决这些问题,而且能够使代码简洁优雅易于维护。
简洁明了了许多吧:smile:
jQuery.when 的参数
上面提到将多个异步请求作为参数传入 jQuery.when 方法中,这个描述并不正确,因为 jQuery.when 接受的是延迟对象(jQuery.Deferred),巧在 jQuery.ajax 方法返回的 jqXHR 对象(浏览器原生 XHR 对象的超集)就是一个延迟对象(jQuery 1.5+),所以看上去我们是将 jqXHR 对象作为了参数,这确实让人产生了一定的误解。
在处理普通的延迟问题的时候,我们就需要在异步方法中明确地返回延迟对象。
done、fail、then 方法
jQuery.when 方法返回的是一个 Promise 对象(延迟对象的一个子集),可以调用它的
done
、fail
、then
方法执行回调函数。这里列一下这些方法中回调函数的执行条件。另外需要注意的是,当 jQUery.when 方法被传入了一个以上的参数时,回调函数中的参数可能是一个数组。因为在传递给一个延迟对象的解决(resolved)事件为多个值的情况下,相应的参数将是这些值组成的数组。
参考资料
jQuery.ajax API 传送门 jQuery.when API 传送门
Thanks