2013-11-21 134 views
1

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

你可以发布你正在传递的回调的例子吗? –

+0

另外,它怎么不工作?什么都没发生......抛出一个错误..? –

回答

1

你不能在javascript中用这样的while循环轮询,并期望适当的性能。 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调用)的关键)。

+0

感谢您的帮助;) – kDeveloper

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)); 
    }); 
} 
+0

感谢您的帮助:) – kDeveloper