2011-07-31 89 views
0

我正在用維基百科api構建一個自動提示框,並且問題是DOM的更新順序基於從服務器檢索到的響應順序,而實際上應該依賴於順序發射的onkeyup事件。 因此,如果即時尋找Lady Gaga和我按L然後如果a。現在我從哪裏找的L請求的響應來晚於響應爲La然後DOM與升的反應不應該發生,因爲我最近更新的最近的輸入是La構建一堆JSONP請求

因此在每個onkeyup事件創建具有創建請求時的時間戳(onkeyup事件發射)一個Request對象並將其存儲一個全局數組requests。還存在全局變量lastValidRequest,其存儲實際修改爲DOM的最後一個對象Request的時間戳。在回調函數中,我檢查一個Request的時間戳是否小於lastValidRequest,並放棄這些請求,因爲它們比他們發送的舊和更新Request。我盡我所能地評論了代碼,使每件事都容易理解。該代碼看起來像這樣

<script type="text/javascript"> 
    var requests=new Array(); // array to hold requests 

    var lastValidRequest=(new Date()).getTime(); // shows the time of the last request whose callback function was called 

    function cb(data) // calls send method of Request object 
    { 
     requests[requests.length-1].send(data); //this is where i m going wrong but i dont know wat to do here 
    } 

    function Request(url) //request constructor 
    { 
     this.time=(new Date()).getTime(); //time at which request was created 
     this.url=url+"&callback=cb"; 
     this.node=document.createElement('script'); 
     this.node.src=this.url; 
     this.ran=false; // indicates whether this request modified the div element's contents,just used for making debuuging easy 
     return this; 
    }; 

    Request.prototype.send=function(data) { 
     if (this.time < lastValidRequest) // check if a newer request has been made 
     { 
      this.node.parentNode.removeChild(this.node); // cancel the request 
      //this.node=null; 
     } 
     else        // this is the newest request 
     { 
      lastValidRequest=this.time; //set lastValidRequest to time of this request 
      this.ran=true;  
      var str=""; 
      for(var i=0;i<data[1].length;i++) 
       str=str+data[1][i]+"</br>"; 
      document.getElementById('content').innerHTML=str; 
      this.node.parentNode.removeChild(this.node); 
     } 
    }; 


    window.onload=function() 
    { 
     textbox=document.getElementById('search'); 
     textbox.onkeyup=function() { 
      var text=textbox.value;  // text is the query for the GET request 
      if(text=="") 
      { 
       document.getElementById('content').innerHTML=""; 
       return; 
      } 
      var url="http://en.wikipedia.org/w/api.php?action=opensearch&search=" +text + "&limit=10&namespace=0&format=json"; 
      requests.push(new Request(url)); // create a new request and add it to the end of the array 
      document.body.appendChild(requests[requests.length-1].node); 
     } 
    } 
</script> 

有這個代碼的pastebin鏈接here


UPDATE

我已經找到了如何逃脫的wikipedia api因爲當它返回一個它也會返回搜索查詢。例如,如果我搜索gaga然後返回的響應JSON是本

["gaga",["GaGa","GAGA","Gagarin's Start","Gagauz people","Gagauzia","Gaga","Gagaku","Gagauz language","Gagarin","Gagan Narang"]] 

現在我可以很容易地找出哪些響應屬於哪個請求。所以我可以做這樣的事情,看看是否反應是最近的請求

if (textbox.value==data[0]) //check if searchbox's value is same as JSON's first element 
{ 
//update dom because response its for latest request 
} 

,但我尋找的東西是

我如何關聯對象的響應;一般的請求?

這是我如何決定哪些響應屬於哪個請求(我是在假設到?

+0

您解釋了您的代碼的功能,但不清楚您遇到的問題是什麼。它可以工作嗎?順便提一下,你是否包含了所有的代碼? (我問,因爲我看不到有關提交請求的代碼。) – cheeken

+0

@cheeken將'script'element添加到'dom'時提交請求。問題在於'div'的更新順序取決於從服務器接收響應的順序,它實際上取決於'onkeyup'事件的觸發事件 – lovesh

+0

如果您做了足夠* *相同*請求以獲得這混在一起,你可能經常碰到服務器。 –

回答

3

你需要做的是:僅允許通過中止以前每次一個一個連接。

不幸的是,我不明白你的代碼不夠好,看到這是如何做到的,但與普通AJAX和jQuery,它看起來像:

<script type="text/javascript"> 
    $(document).ready(function(){ 

     var curr_request=null; 

     $('#autosuggest').keyup(function(){ 

      // abort existing request 
      if(curr_request)curr_request.abort(); 

      // do the request 
      curr_request = $.getJSON(the_url,function(data){ 
       curr_request=null; 
       // populate autosuggest with data 
      }); 

     }); 
    }); 
</script> 

編輯:由於您處理使用JSONP來「中止」請求,您可能必須從文檔中刪除腳本節點。像document.body.removeChild(requests[requests.length-1].node); 如果是這樣,你不需要保留一個堆棧,只需跟蹤最後一個,就像我在我的例子中使用curr_request那樣。

+0

你能指出什麼,你無法理解?我將相應地編輯我的代碼 – lovesh

+1

主要是爲什麼你要保存一整堆請求,包括諸如時間之類的微不足道的事情。此外,通過在它之前添加一個'var'來避免像'textbox'這樣的全局變量。另外,爲什麼有一個完整的對象「請求」呢?如果你重新思考你的過程,你會意識到你只需要一個「請求」,因此不需要堆棧。 – Christian

+0

我不能通過刪除節點來「中止」請求。即使我寫'document.body.appendChild(script); var script = document.createElement(「script」); document.body.removeChild(script);'dom'將被回調函數更新。這就是爲什麼在我的代碼中,只有當我檢測到這是最新的查詢時,我才附加'script'元素 – lovesh