2011-07-31 84 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