在 jQuery 中处理来自 $.when 的动态参数
Handling dynamic arguments from $.when in jQuery
我的 requests
数组中有 ajax 个请求。请求的数量可以是 1,2 或 3(无所谓,动态)。
这样的请求:
var ajaxRequest = $.get(ajaxUrl, requestData);
我想像这样处理结果:
$.when.apply($, requests).then(function () {
$.each(arguments, function (key, value) {
console.log(value);
//var response = JSON.parse(value[0]); //It is fail if there is only 1 ajax request
});
});
问题是arguments
。
如果只有 1 个请求,则每个请求的值将为
string [the json string, what I want to JSON.parse]
string ['success']
Object [the Ajax request Object]
在这种情况下,参数长度为 3,这将导致以后出现问题。
但是,如果我有 2 或 3 个请求,那么我将返回这样的数组(例如 2 个请求):
Array [json string, 'success', ajax Object],
Array [json string, 'success', ajax Object]
如果三个请求,当然多一个数组。
问题就在这里。我无法检查参数的长度,因为如果我有 3 个请求则为 3,如果我只有一个请求则为 3。
所以我重写了我的脚本:
$.each(arguments, function (key, value) {
if (typeof value === 'string') {
var response = JSON.parse(value);
} else {
var response = JSON.parse(value[0]);
}
$('div[data-id="' + response.productId + '"').find('.dictionaryContainer').find('ul').html(response.html);
});
现在我的问题是:
if (typeof value === 'string') {
即使它很好,迭代也是连续的,也许它可以用标志和 return ture
s 以某种方式被破解,但我敢打赌,有一些更优雅的解决方案。
有人可以帮我处理吗?
简单的解决方法是自己检查请求的长度并调整迭代的内容,如下所示:
$.when.apply(null, requests).done(function() {
var arg = (requests.length === 1) ? [arguments] : arguments;
$.each(arg, function(i, response) {
console.log(response);
})
});
像这样fiddle
不幸的是,正如您所发现的那样,$.when
和这种承诺的组合基本上被打破了,因为它的混乱行为取决于您是否将一个或两个以上的参数传递给 $.when
.
我建议:
使用承诺(如果需要,使用 polyfill)和承诺化 $.ajax
、$.get
等;然后在承诺数组上使用 Promise.all
。
实现您自己的 $.whenAll
并不混乱。
以下是两者的粗略版本(仅适用于 $.ajax
,您可以自己制作 $.get
和 $.post
):
#1 的粗略版本:(注意:创建一个新的、干净的承诺而不是重复使用 $.ajax
的承诺,以便 只是 return 结果 [不是 success
的其他参数] 和 return 带有拒绝的单个对象 [不是 error
的各种离散参数]。)
$.promiseAjax = function(options) {
return new Promise(function(resolve, reject) {
options = $.extend({}, {
success: function(result) {
resolve(result);
},
error: function(jqXHR, textStatus, errorThrown) {
reject({
jqXHR: jqXHR,
textStatus: textStatus,
errorThrown: errorThrown
});
}
}, options);
$.ajax(options);
});
};
用法:
var requests = [];
if (someCondition) {
requests.push($.promiseAjax({/*...*/}));
}
if (someotherCondition) {
requests.push($.promiseAjax({/*...*/}));
}
Promise.all(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});
#2 的粗略版本:
$.whenAll = function(promises) {
var d = $.Deferred();
var results = [];
var counter = promises.length;
promises.forEach(function(promise, index) {
promise
.done(function(result) {
results[index] = result;
if (--counter == 0) {
// All done
d.resolve(results);
}
})
.fail(function() {
d.reject(Array.prototype.slice.call(arguments));
});
});
return d.promise();
};
用法:
var requests = [];
if (someCondition) {
requests.push($.ajax({/*...*/}));
}
if (someotherCondition) {
requests.push($.ajax({/*...*/}));
}
$.whenAll(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});
我的 requests
数组中有 ajax 个请求。请求的数量可以是 1,2 或 3(无所谓,动态)。
这样的请求:
var ajaxRequest = $.get(ajaxUrl, requestData);
我想像这样处理结果:
$.when.apply($, requests).then(function () {
$.each(arguments, function (key, value) {
console.log(value);
//var response = JSON.parse(value[0]); //It is fail if there is only 1 ajax request
});
});
问题是arguments
。
如果只有 1 个请求,则每个请求的值将为
string [the json string, what I want to JSON.parse]
string ['success']
Object [the Ajax request Object]
在这种情况下,参数长度为 3,这将导致以后出现问题。
但是,如果我有 2 或 3 个请求,那么我将返回这样的数组(例如 2 个请求):
Array [json string, 'success', ajax Object],
Array [json string, 'success', ajax Object]
如果三个请求,当然多一个数组。
问题就在这里。我无法检查参数的长度,因为如果我有 3 个请求则为 3,如果我只有一个请求则为 3。
所以我重写了我的脚本:
$.each(arguments, function (key, value) {
if (typeof value === 'string') {
var response = JSON.parse(value);
} else {
var response = JSON.parse(value[0]);
}
$('div[data-id="' + response.productId + '"').find('.dictionaryContainer').find('ul').html(response.html);
});
现在我的问题是:
if (typeof value === 'string') {
即使它很好,迭代也是连续的,也许它可以用标志和 return ture
s 以某种方式被破解,但我敢打赌,有一些更优雅的解决方案。
有人可以帮我处理吗?
简单的解决方法是自己检查请求的长度并调整迭代的内容,如下所示:
$.when.apply(null, requests).done(function() {
var arg = (requests.length === 1) ? [arguments] : arguments;
$.each(arg, function(i, response) {
console.log(response);
})
});
像这样fiddle
不幸的是,正如您所发现的那样,$.when
和这种承诺的组合基本上被打破了,因为它的混乱行为取决于您是否将一个或两个以上的参数传递给 $.when
.
我建议:
使用承诺(如果需要,使用 polyfill)和承诺化
$.ajax
、$.get
等;然后在承诺数组上使用Promise.all
。实现您自己的
$.whenAll
并不混乱。
以下是两者的粗略版本(仅适用于 $.ajax
,您可以自己制作 $.get
和 $.post
):
#1 的粗略版本:(注意:创建一个新的、干净的承诺而不是重复使用 $.ajax
的承诺,以便 只是 return 结果 [不是 success
的其他参数] 和 return 带有拒绝的单个对象 [不是 error
的各种离散参数]。)
$.promiseAjax = function(options) {
return new Promise(function(resolve, reject) {
options = $.extend({}, {
success: function(result) {
resolve(result);
},
error: function(jqXHR, textStatus, errorThrown) {
reject({
jqXHR: jqXHR,
textStatus: textStatus,
errorThrown: errorThrown
});
}
}, options);
$.ajax(options);
});
};
用法:
var requests = [];
if (someCondition) {
requests.push($.promiseAjax({/*...*/}));
}
if (someotherCondition) {
requests.push($.promiseAjax({/*...*/}));
}
Promise.all(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});
#2 的粗略版本:
$.whenAll = function(promises) {
var d = $.Deferred();
var results = [];
var counter = promises.length;
promises.forEach(function(promise, index) {
promise
.done(function(result) {
results[index] = result;
if (--counter == 0) {
// All done
d.resolve(results);
}
})
.fail(function() {
d.reject(Array.prototype.slice.call(arguments));
});
});
return d.promise();
};
用法:
var requests = [];
if (someCondition) {
requests.push($.ajax({/*...*/}));
}
if (someotherCondition) {
requests.push($.ajax({/*...*/}));
}
$.whenAll(requests).then(function(results) {
// `results` will reliably be an array of the results, even when
// there's only one request
});