构建 JSONP 请求堆栈
我正在使用 wikipedia api 构建一个自动建议框,问题是 DOM
的更新顺序基于从服务器检索的响应顺序,而它实际上应该取决于顺序触发 onkeyup
事件。 因此,如果我正在寻找 Lady Gaga
,然后按 L
,然后按 a
。现在,如果我正在寻找 的请求的响应>L
晚于 La
的响应,然后 DOM
使用 L 的响应更新,这不应该发生,因为我最近的输入是 La.
因此,在每个 onkeyup
事件上,创建一个 Request
对象,该对象具有创建请求时的时间戳(触发 onkeyup
事件)并将其存储在全局数组 requests
。还有一个全局变量lastValidRequest
,它存储实际修改DOM
的最后一个Request
对象的时间戳。在回调函数中,我检查时间戳是否小于 lastValidRequest
的 Request
并丢弃这些请求,因为它们比它们旧的和新的 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
链接这里
更新< /strong>
我已经弄清楚如何摆脱 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
}
,但我正在寻找的确切内容是
如何将请求与一般响应关联起来?
这就是如何做我决定哪个响应属于哪个请求(我是否过度假设?)
i am building an auto suggest box with wikipedia api and the problem is that the order of updates to DOM
is based on the order of responses retrieved from the server whereas it should actually depend on the order of firing of onkeyup
event.
so if i m looking for Lady Gaga
and i press L
and then a
.now if the response from the request where i am looking for L
comes later than response for La
then DOM
is updated with response of L which should not happen because my most recent input is La
.
Therefore on every onkeyup
event a create a Request
object that has the timestamp of when the request was created(onkeyup
event fired) and store it a global array requests
. also there is global variable lastValidRequest
that stores the timestamp of the last Request
object that actually modified DOM
. In the callback function i check whether a Request
whose timestamp is less than lastValidRequest
and discard those requests because they are old and newer Request
than them has been sent. I have commented the code to my best to make every-thing easily understandable. The code looks like this
<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>
there is pastebin
link of this code here
UPDATE
i have figured out how to get away with the wikipedia api
because when it returns a response for a search it also returns the search query. for example if i search for gaga
then the JSON
response returned is this
["gaga",["GaGa","GAGA","Gagarin's Start","Gagauz people","Gagauzia","Gaga","Gagaku","Gagauz language","Gagarin","Gagan Narang"]]
now i can easily figure out which response belongs to which request. So i can do something like this to see if the response is for the most recent request
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
}
but the exact thing i am looking for is
HOW DO I ASSOCIATE A REQUEST WITH A RESPONSE IN GENERAL?
that is how do i decide which response belongs to which request (am i over hypothesizing?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要做的是通过中止前一个连接来一次只允许一个连接。
不幸的是,我不太了解你的代码,无法了解这是如何完成的,但是使用常规 AJAX 和 jQuery,它看起来像:
编辑: 由于你正在处理 JSONP,因此“中止" 请求,您可能必须从文档中删除脚本节点。类似
document.body.removeChild(requests[requests.length-1].node);
如果是这样,您也不需要保留堆栈,只需跟踪最后一个堆栈即可,就像我在示例中对
curr_request
所做的那样。What you need to do is to only allow one connection at a time by aborting the previous one.
Unfortunately, I didn't understand your code well enough to see how this is done, but with regular AJAX and jQuery, it would look like:
Edit: Since you're dealing with JSONP, to "abort" a request, you would probably have to remove the script node from the document. Something like
document.body.removeChild(requests[requests.length-1].node);
If so, you don't need to keep a stack as well, just keep track of the last one, as I did with
curr_request
in my example.