存储在对象中的函数的回调

时间:2013-11-21 07:04:08

标签: javascript callback xmlhttprequest

我需要做一个连续的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();
}

谢谢你们的帮助;)

2 个答案:

答案 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));   
  });
}