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

Callback of function stocked in an object

本文关键字:函数 回调 对象 存储      更新时间:2023-09-26

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

谢谢你们的帮助;)

您不能用这样的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调用这样的异步操作的关键)。

在这一行: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));   
  });
}