我试图在stackoverflow上阅读很多答案,但大多数问题似乎比我的要简单一些。我想做的是:
这是我的代码:
var chainedPromise = new Array();
//Build a .then() chain by assignment
for (i = 0; i < requests.length; i++) {
(function(i){
chainedPromise = $.when().then(function(){
return get_results_ajax(table, idRows, requests[i-1], requests[i], type, cfg.siteroot);
});
})(i);
}
var Promise = $.when(chainedPromise).then(function(){
return get_stats_ajax(table, idRows, type, cfg.siteroot);
}).then(function() {
return get_free_ajax(table,idRows, type, cfg.siteroot);
});
请求包含一个数字列表:[100,200,300,400],最多5000个。 每个请求应发回100个表行。这可以正常工作。
在我检索完所有数据后执行统计和自由操作不起作用。因此,显然,最后两个调用的链接需要以不同的方式完成,但我不明白应该如何完成。
ajax调用是这样的:
function get_results_ajax(table, idRows, start, stop, type, siteroot) {
var deferred = jQuery.Deferred();
var request = jQuery.ajax({
type : 'POST'
url : siteroot+"/index.php?page=ajax",
data : "type="+type+"&idRows="+idRows+"&start="+start+"&stop="+stop,
dataType : 'json',
});
request.success(function(data) {
table.rows.add(data).draw();
});
request.done(function(msg, textStatus, jqXHR) {
if (jqXHR.status === 200) {
deferred.resolve(jqXHR.responseText);
}
console.log("Returned data from " + start + " to " + stop);
});
request.fail(function(msg, textStatus, jqXHR) {
console.log("The server is taking too long to respond. Start: " + start + " Stop: " + stop);
deferred.reject("HTTP error: " + jqXHR.status);
});
return deferred.promise();
}
答案 0 :(得分:0)
首先,这里有几个错误:
var chainedPromise = new Array();
//Build a .then() chain by assignment
for (i = 0; i < requests.length; i++) {
(function(i){
chainedPromise = $.when().then(function(){
return get_results_ajax(table, idRows, requests[i-1], requests[i], type, cfg.siteroot);
});
})(i);
}
var Promise = $.when(chainedPromise).then(function(){
return get_stats_ajax(table, idRows, type, cfg.siteroot);
}).then(function() {
return get_free_ajax(table,idRows, type, cfg.siteroot);
});
chainedPromise
是一个数组,您希望它保持为数组,以便将其传递给$.when()
。要向数组添加值,请使用.push()
。您只是分配给chainedPromise
,它只是用新值替换它,它不再是数组。
get_results_ajx()
会返回一个承诺,因此您可以直接使用该承诺。无需在其前面使用$.when().then(...)
。
$.when()
不直接接受数组(如果你问我,jQuery的愚蠢设计决定),而是采用一系列单独的参数,所以要传递一个数组,你有使用.apply()
将数组转换为参数列表。
当你有一个数组要处理成一组promises时,使用.map()
比使用for
循环要容易得多。
你有一个循环,数组索引从0开始,你尝试引用requests[i-1]
,这将在循环的第一次迭代中给你undefined
,因为i-1 === -1
。我不知道你对第一次迭代的意图。您的意思是在i = 1
开始迭代吗?
因此,除了您仍然需要修复上面的第5项之外,所有初始代码都可以更改为:
var promiseArray = requests.map(function(item, i) {
return get_results_ajax(table, idRows, requests[i-1], requests[i], type, cfg.siteroot);
});
$.when.apply($, promiseArray).then(function() {
return get_stats_ajax(table, idRows, type, cfg.siteroot);
}).then(function() {
return get_free_ajax(table,idRows, type, cfg.siteroot);
});
然后,你的get_results_ajax()
使事情变得更加复杂。 jQuery&#39; s $.ajax()
已经返回一个承诺。您可以直接使用它,而不需要创建自己的延迟。实际上,将其包装在另一个延迟中称为promise anti-pattern。
所以,这个:
function get_results_ajax(table, idRows, start, stop, type, siteroot) {
var deferred = jQuery.Deferred();
var request = jQuery.ajax({
type : 'POST'
url : siteroot+"/index.php?page=ajax",
data : "type="+type+"&idRows="+idRows+"&start="+start+"&stop="+stop,
dataType : 'json',
});
request.success(function(data) {
table.rows.add(data).draw();
});
request.done(function(msg, textStatus, jqXHR) {
if (jqXHR.status === 200) {
deferred.resolve(jqXHR.responseText);
}
console.log("Returned data from " + start + " to " + stop);
});
request.fail(function(msg, textStatus, jqXHR) {
console.log("The server is taking too long to respond. Start: " + start + " Stop: " + stop);
deferred.reject("HTTP error: " + jqXHR.status);
});
return deferred.promise();
}
可以成为这个:
function get_results_ajax(table, idRows, start, stop, type, siteroot) {
return jQuery.ajax({
type : 'POST'
url : siteroot+"/index.php?page=ajax",
data : "type="+type+"&idRows="+idRows+"&start="+start+"&stop="+stop,
dataType : 'json',
}).then(function(data) {
table.rows.add(data).draw();
});
}
我改变的事情:
jQuery.ajax()
承诺。无需创建延期。.then()
而不是jQuery专有.done()
。由于jQuery支持.then()
并且它现在是ES6中的标准,所以要继续前进。