相信大家在面对一个 没有 requirejs、seajs、webpack等遵循commonjs规范的项目的时候,想要使用jQuery的ajax同时请求不互相依赖的多个文件(例如一些地图数据的json文件:country.json、country-i18n.json、provinces.json、provinces-i18n.json等)或数据(由多个请求拿到的数据组成),当这些请求都完成时才执行函数的时候,一般会这么写:
//例如
$.getJSON('./json/country.json',function(data1){
$.getJSON('./json/country-i18n.json',function(data2){
$.getJSON('./json/provinces.json',function(data3){
$.getJSON('./json/provinces-i18n.json',function(data4){
//更多嵌套...
//需要同时拿到data1、data2、data3、data4才能画图
//因为这几个json(每个体积不一样大或网络影响)无法确定请求完成时间,谁快谁慢,所以需要嵌套请求
})
})
});
});
看起来就很恶心,而且极大的影响了程序执行的速度,如下图:
但是我们希望是这样的,所有请求是同时的,并且当这些请求都完成时执行函数,如下图:
代码如下:
//例如
var times = 0,files = ['country','country-i18n','provinces','provinces-i18n'],datas = {};
files.forEach(function(file){
$.getJSON('./json/' + file + '.json',function(data){
datas[file] = data;
trigger();
});
});
function trigger() {
times++;
if (times === files.length) {
complete()
}
}
function complete(){
//do something...
}
最终封装后的代码如下:
;(function($){
/**
* $.ajaxs
* 批量同时发送异步ajax请求。
* (注意:请求是无序的,若要有序,则可设置globalOpt为true或{byOrder: true},此时是非同时的)。
*
* @param {Array} opts - 放置ajax配置的数组;
* 可以是:[{},{},...] 、[url_1,url_2,...];
* 每个opt对象的配置就是$.ajax的配置。
* @param {function} [fn] - 当所有的请求成功时的回调函数。
* @param {Object|boolean} [globalOpt] - 每个opts配置的共同设置;
* 类似于$.ajax的配置,多了个byOrder属性;
* (注意:个别的会覆盖全局的)。
* @returns {Object} - jQuery对象。
*/
$.extend({
ajaxs: function (opts, fn, globalOpt) {
var times = 0, byOrder = false, datas = [];
if (typeof globalOpt === 'boolean') {
byOrder = globalOpt;
globalOpt = {byOrder: byOrder};
} else {
byOrder = globalOpt.byOrder;
}
$.each(opts, function (i, opt) {
opt = typeof opt === 'object' ? opt : {url: opt};
var _globalOpt = $.extend(true, {}, globalOpt),
_success = opt.success || _globalOpt.success || $.noop,
_opt = $.extend(_globalOpt, opt, {
success: function (data, textStatus, $XHR) {
_success(data, textStatus, $XHR, i);
datas[i] = data;
trigger();
}
});
byOrder ? (opts[i] = _opt) : $.ajax(_opt);
});
byOrder && $.ajax(opts[times]);
function trigger() {
times++;
if (times === opts.length) {
fn && fn(datas);
} else {
byOrder && $.ajax(opts[times]);
}
}
return this;
}
});
})(jQuery);