Javascript 如何确保包含多个$.ajax调用的函数完全同步运行,并允许在执行时重新绘制浏览器
我一直致力于将函数写入: 1) 使用$.ajax调用处理输入数组以填充输出数组(下面是inputList) 2) 以下是我所拥有的,但我有一些问题:Javascript 如何确保包含多个$.ajax调用的函数完全同步运行,并允许在执行时重新绘制浏览器,javascript,jquery,ajax,settimeout,Javascript,Jquery,Ajax,Settimeout,我一直致力于将函数写入: 1) 使用$.ajax调用处理输入数组以填充输出数组(下面是inputList) 2) 以下是我所拥有的,但我有一些问题: 当我调用requestData()时,它直接运行到处理outputList数组,而没有完全填充/填充它-它将一个值放入其中,然后开始处理该值,但该函数显然仍然以异步方式单独运行到后续处理。我需要它是完全同步的,这样它在inputList数组被完全处理之前不会返回 我没有看到浏览器在每次调用runajax()函数时都会重新绘制其html更新的div
- 当我调用requestData()时,它直接运行到处理outputList数组,而没有完全填充/填充它-它将一个值放入其中,然后开始处理该值,但该函数显然仍然以异步方式单独运行到后续处理。我需要它是完全同步的,这样它在inputList数组被完全处理之前不会返回
- 我没有看到浏览器在每次调用runajax()函数时都会重新绘制其html更新的div,我正在尝试使用setTimeout来完成这项工作
//declare holding function requestData - expects a non-empty input data array named inputList
function requestData() {
//declare inner function runajax
function runajax() {
if(inputList.length > 0) {
//get first item from inputlist and shorten inputList
var data = $.trim(inputList.shift());
function getData() {
//send the data to server
return $.ajax({
url: 'sada_ajax_fetch_data.php',
cache: false,
async: false,
method: "post",
timeout: 2000,
data: {
requesttype: "getmydata",
email: encodeURIComponent(data)
}
});
}
function handleReturnedData (response) {
response = $.trim(decodeURIComponent(response));
//update the div inner html
if(response == "Failed") {
$('#fetchupdatestatus').html('There was an error retrieving the data you requested!');
} else {
$('#fetchupdatestatus').html('The item returned was '+response);
}
//add the response from ajax to the end of the outputList array
outputList.push(response);
//set up the next ajax call
var doNextBitOfWork = function () {
runajax();
};
//call setTimeout so that browser shows refreshed div html
setTimeout(doNextBitOfWork, 0);
//return
return $.when();
}
//do the next ajax request and response processing
return getData().done(handleReturnedData);
} else {
//did the last one so return
return $.when();
}
}
//kick off the ajax calls
runajax();
}
var inputList = new Array();
var outputList = new Array();
.....load +/- 100 values to be processed using ajax into array inputList
requestData();
.....process stuff in array outputList
.....etc
之前我的回答是“你做错了”,但后来我决定展示一下,你如何(几乎)做对:
var请求\u生成器={
工作:假,
队列:[],
输出:[],
requestData:函数(inputList){
if(request_maker.working==true){
返回false;
}
请求_maker.output=[];
请求_maker.working=true;
while(inputList.length>0){
var data=$.trim(inputList.shift());
请求\u maker.queue.push(数据);
}
日志(请求生成者队列);
请求生成者doTheJob();
返回true;
},
doTheJob:function(){
当前_data_to_send=request_maker.queue.shift();
日志(当前要发送的数据);
if(要发送的当前数据类型!=“未定义”&&request\u maker.queue.length>=0){
$.ajax({
url:“/echo/json/”,
cache:false,
方法:“张贴”,
超时时间:2000,
数据:{
requesttype:“getmydata”,
电子邮件:encodeURIComponent(当前数据发送)
},
成功:功能(数据、状态、xhrobject){
console.log(xhrobject);
请求制造商的handleReturnedData(数据);
},
});
}否则{
请求_maker.working=false;
log(“所有数据都已发送”);
}
},
HandlerReturnedData:函数(响应){
控制台日志(响应);
响应=$.trim(组件(响应));
//response='Failed';//取消注释以模拟此类响应
如果(响应=“失败”){
$('#fetchupdatestatus').append('检索您请求的数据时出错!
');
}否则{
$('#fetchupdatestatus').append('返回的项为'+response+'
');
请求/输出/推送(响应);
}
请求生成者doTheJob();
if(request_maker.working==false){
log(“所有请求都已完成”);
console.log(请求生成程序输出);
}
}
}
inputList=[1,2,3,4,5,6];
if(请求\制造商请求数据(输入列表)){
console.log('startedworking');
}
如果(!request_maker.requestData(inputList)){
log('正在工作,稍后再试');
}
请注意,我已将请求路径更改为JSFIDLE的ajax模拟链接,并将html()
替换为append()
调用,以在div中打印文本。这些调用的执行和处理顺序与inputList
中的相同,但它们不会锁定用户的浏览器<代码>请求制造商。输出的元素顺序也与输入列表
中的元素顺序相同
请记住,您还需要添加错误
处理(可能只是一个将“错误”字符串推入输出
而不是结果的函数),否则任何ajax错误(403/404/502等)都将使其“卡在”工作状态。或者,您可以使用complete
而不是success
来检查请求状态
UPD:问题的答案:你不能同时得到这两个。您可以在异步请求之间使用回调并让浏览器重新绘制,或者使请求同步并阻止浏览器,直到代码完成工作
UPD2:实际上有一些关于强制重画的信息,但我不知道它是否对您有效:前面我的回答是“您做得不对”,但后来我决定展示一下,您如何(几乎)正确地做:
var请求\u生成器={
工作:假,
队列:[],
输出:[],
requestData:函数(inputList){
if(request_maker.working==true){
返回false;
}
请求_maker.output=[];
请求_maker.working=true;
while(inputList.length>0){
var data=$.trim(inputList.shift());
请求\u maker.queue.push(数据);
}
日志(请求生成者队列);
请求生成者doTheJob();
返回true;
},
doTheJob:function(){
当前_data_to_send=request_maker.queue.shift();
日志(当前要发送的数据);
if(要发送的当前数据类型!=“未定义”&&request\u maker.queue.length>=0){
$.ajax({
url:“/echo/json/”,
cache:false,
方法:“张贴”,
超时时间:2000,
数据:{
requesttype:“getmydata”,
电子邮件:encodeURIComponent(当前数据发送)
},
成功:功能(数据、状态、xhrobject){
console.log(xhrobject);
请求制造商的handleReturnedData(数据);
},
});
}否则{
请求_maker.working=false;
log(“所有数据都已发送”);
}
},
手推车
var request_maker = {
working: false,
queue: [],
output: [],
requestData: function(inputList) {
if (request_maker.working == true) {
return false;
}
request_maker.output = [];
request_maker.working = true;
while (inputList.length > 0) {
var data = $.trim(inputList.shift());
request_maker.queue.push(data);
}
console.log(request_maker.queue);
request_maker.doTheJob();
return true;
},
doTheJob: function() {
current_data_to_send = request_maker.queue.shift();
console.log(current_data_to_send);
if (typeof current_data_to_send != 'undefined' && request_maker.queue.length >= 0) {
$.ajax({
url: '/echo/json/',
cache: false,
method: "post",
timeout: 2000,
data: {
requesttype: "getmydata",
email: encodeURIComponent(current_data_to_send)
},
success: function(data, status, xhrobject) {
console.log(xhrobject);
request_maker.handleReturnedData(data);
},
});
} else {
request_maker.working = false;
console.log('all data has been sent');
}
},
handleReturnedData: function(response) {
console.log(response);
response = $.trim(decodeURIComponent(response));
//response= 'Failed';//uncomment to emulate this kind of response
if (response == "Failed") {
$('#fetchupdatestatus').append('There was an error retrieving the data you requested!<br/>');
} else {
$('#fetchupdatestatus').append('The item returned was ' + response + '<br/>');
request_maker.output.push(response);
}
request_maker.doTheJob();
if (request_maker.working == false) {
console.log('all requests have been completed');
console.log(request_maker.output);
}
}
}
inputList = [1, 2, 3, 4, 5, 6];
if (request_maker.requestData(inputList)) {
console.log('started working');
}
if (!request_maker.requestData(inputList)) {
console.log('work in progress, try again later');
}