我需要做一个连续的XMLHttpRequest请求(FIFO),不要同时用多个请求调用服务器,我写了这个顺序执行XMLHttpRequest的函数:
var queue = [];
var xmlHttpCurrentlyOccuped = false;
function loadUserDetails() {
var url = "https://someurl.com";
doWebRequest("GET", url, "", parseUserDetails);
}
function parseUserDetails(dataFromServer){
Console.log("data received from server: "+JSON.stringify(dataFromServer));
}
function doWebRequest(method, url, params, callback) {
var parametres = new Object();
parametres.myMethod = method;
parametres.myUrl = url;
parametres.myParams = params;
parametres.myCallback = callback;
queue.push(parametres);
while (queue.length>0 && !xmlHttpCurrentlyOccuped){
var doc = new XMLHttpRequest();
doc.onreadystatechange = function() {
var status;
if (doc.readyState == XMLHttpRequest.LOADING || doc.readyState == XMLHttpRequest.OPENED){
xmlHttpCurrentlyOccuped = true;
}
if (doc.readyState == XMLHttpRequest.DONE && doc.status == 200) {
xmlHttpCurrentlyOccuped = false;
var data;
var contentType = doc.getResponseHeader("Content-Type");
data = doc.responseText;
queue[0].myCallback(data);
queue.shift();
}
else if (doc.readyState == XMLHttpRequest.DONE) {
xmlHttpCurrentlyOccuped = false;
status = doc.status;
if(status!=200) {
parseTheError(url);
}
queue.shift();
}
}
doc.open(queue[0].myMethod, queue[0].myUrl);
doc.send();
}
}
我的问题是,在XMLHttpRequest完成之后,回调函数在我的代码queue[0].myCallback(data);
的这一行中不起作用我有这个错误:“queue [0] .callback(data):undefined”。
有什么想法解决这个问题吗?
更新 我解决了这个问题,这是我的工作代码,也许它可以帮助某人:
var queue = [];
function doWebRequest(method, url, params, callback) {
var parametres = new Object();
parametres.myMethod = method;
parametres.myUrl = url;
parametres.myParams = params;
parametres.myCallback = callback;
if (queue.length>0) {if (queue[queue.length-1].url != parametres.url) queue.push(parametres);}
else queue.push(parametres);
var doc = new XMLHttpRequest();
function processNextInQueue() {
if (queue.length>0){
var current = queue.shift();
doc.onreadystatechange = function() {
if (doc.readyState == XMLHttpRequest.DONE){
if(doc.status == 200) {
if(typeof current.myCallback == 'function'){
current.myCallback(doc.responseText)
} else {
console.log('Passed callback is not a function');
}
processNextInQueue();
}
else if(doc.status!=200) {
parseTheErrors(current.myUrl);
}
}
}
doc.open(current.myMethod, current.myUrl);
doc.send();
}
}
processNextInQueue();
}
谢谢你们的帮助;)
答案 0 :(得分:1)
您不能使用像这样的while循环在javascript中进行轮询并期望正常的性能。 Javascript是单线程的,因此当您像这样进行轮询时,您不允许任何周期发生其他事情。您需要学习如何在启动第一个ajax调用然后返回时编写异步代码。当第一个完成时,然后开始第二个,依此类推。
这是一种方法:
queue.push(parametres);
function processNextInQueue() {
if (queue.length) {
var doc = new XMLHttpRequest();
doc.onreadystatechange = function() {
if (doc.readyState == XMLHttpRequest.DONE) {
if (doc.status == 200) {
queue[0].myCallback(doc.responseText);
} else {
fonctionPourAnalyserLErreur(url);
}
// done now so remove this one from the queue
// and start the next one
queue.shift();
processNextInQueue();
}
}
doc.open(queue[0].myMethod, queue[0].myUrl);
doc.send();
}
}
processNextInQueue();
这个想法是你开始第一个ajax调用,然后你就回来了。当readystatechange显示完成后,您将处理结果,然后触发下一个结果。在ajax调用正在进行的过程中,javascript引擎可以自由地为其他事件提供服务并执行其他操作(这是处理异步操作(如ajax调用)的关键)。
答案 1 :(得分:0)
在这一行:queue[0].myCallback(data)
,出于调试目的(并防止错误破坏您的网站),我将更改为以下内容:
var current = queue.shift();
if(typeof current.myCallback == 'function'){
current.myCallback(data)
} else {
// for now, log it
console.log('Passed callback is not a function');
}
另外,您是否尝试过传递匿名函数以确保它不是范围/函数提升问题?
function loadUserDetails() {
var url = "https://someurl.com";
doWebRequest("GET", url, "", function(dataFromServer){
console.log("data received from server: "+JSON.stringify(dataFromServer));
});
}