我正在执行一些重复的AJAX调用,其中我将一个数组从前端传递到后端,并且每当返回前端时,该数组就会变小(减1),最终它将为空,因此我的递归调用将停止。
这是我的电话:
function download_required_files(demo_data) {
var ajaxsecurity = setup_page_params.ajax_nonce;
jQuery.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: {
action: 'download_import_files_request',
security: ajaxsecurity,
content_install_request_data: JSON.stringify(demo_data),
},
success: function (response) {
console.log(response);
var data = response.data || false;
/**
* If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
*/
if(!data.remaining_steps || !data.remaining_steps.length) {
return false;
}
if(data.can_continue !== 'yes') {
return false;
}
if(data.remaining_steps && data.remaining_steps.length) {
demo_data.steps_to_take = data.remaining_steps;
download_required_files(demo_data);
}
$('.demo-loader-content').fadeOut();
},
error: function (response) {
$('.demo-loader-content').fadeOut();
}
});
}
假设我有2个步骤要下载文件,则此download_required_files
将运行两次,然后将其完成,但是如果我这样做:
var download_process = download_required_files(demo_data) //Runs 2 times
download_process.done(function() { //Do stuff here once that function ran 2 times });
它给了我Cannot read property 'done' of undefined
错误,这是有充分理由的。 download_process
并不是拥有该属性的承诺对象,而只是...空的。
我应该在哪里{@ {1}}进行干预,以便它向外部代码发出信号:“嘿,在应许环境中,我完成了!”
答案 0 :(得分:0)
尽管对$.ajax
的调用的结果是一个jqXHR
对象,该对象类似于promise,对于您描述的内容,我认为我会使用您自己的本地Promise(或{{3 }}(如果您愿意)代表整个递归过程:
function download_required_files(demo_data) {
return new Promise(function(resolve, reject) {
function worker() {
var ajaxsecurity = setup_page_params.ajax_nonce;
jQuery.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: {
action: 'download_import_files_request',
security: ajaxsecurity,
content_install_request_data: JSON.stringify(demo_data),
},
success: function (response) {
console.log(response);
var data = response.data || false;
/**
* If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
*/
if(!data.remaining_steps || !data.remaining_steps.length) {
// *** All done
$('.demo-loader-content').fadeOut();
resolve();
} else if(data.can_continue !== 'yes') {
// *** All done; but is this an error condition? If so
// use `reject` instead of `resolve` below.
$('.demo-loader-content').fadeOut();
resolve();
} else {
demo_data.steps_to_take = data.remaining_steps;
worker(); // This is the internal recursive call
}
},
error: function (response) {
$('.demo-loader-content').fadeOut();
}
});
}
worker();
});
}
或改为使用Deferred
:
function download_required_files(demo_data) {
var d = $.Deferred();
function worker() {
var ajaxsecurity = setup_page_params.ajax_nonce;
jQuery.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: {
action: 'download_import_files_request',
security: ajaxsecurity,
content_install_request_data: JSON.stringify(demo_data),
},
success: function (response) {
console.log(response);
var data = response.data || false;
/**
* If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
*/
if(!data.remaining_steps || !data.remaining_steps.length) {
// *** All done
$('.demo-loader-content').fadeOut();
d.resolve();
} else if(data.can_continue !== 'yes') {
// *** All done; but is this an error condition? If so
// use `d.reject` instead of `d.resolve` below.
$('.demo-loader-content').fadeOut();
d.resolve();
} else {
demo_data.steps_to_take = data.remaining_steps;
worker(); // This is the internal recursive call
}
},
error: function (response) {
$('.demo-loader-content').fadeOut();
}
});
}
worker();
return d.promise();
}
答案 1 :(得分:0)
这是我的方法,将单个AJAX请求与内容循环以及DOM更新分开:
function download_one_file(demo_data) {
return jQuery.ajax({
url: ajaxurl,
type: 'POST',
dataType: 'json',
data: {
action: 'download_import_files_request',
security: setup_page_params.ajax_nonce,
content_install_request_data: JSON.stringify(demo_data),
}
});
}
function download_loop(demo_data) {
return download_one_file(demo_data).then(function(data) {
if (!data) {
return Promise.reject();
} else if (data.remaining_steps && data.remaining_steps.length) {
demo_data.steps_to_take = data.remaining_steps;
return download_loop(demo_data);
} else {
return Promise.resolve();
}
});
}
function download_required_files(demo_data) {
return download_loop(demo_data).finally(function() {
$('.demo-loader-content').fadeOut();
});
}