构建 JSONP 请求堆栈

发布于 2024-11-27 00:15:35 字数 3770 浏览 3 评论 0原文

我正在使用 wikipedia api 构建一个自动建议框,问题是 DOM 的更新顺序基于从服务器检索的响应顺序,而它实际上应该取决于顺序触发 onkeyup 事件。 因此,如果我正在寻找 Lady Gaga,然后按 L,然后按 a。现在,如果我正在寻找 的请求的响应>L 晚于 La 的响应,然后 DOM 使用 L 的响应更新,这不应该发生,因为我最近的输入是 La.

因此,在每个 onkeyup 事件上,创建一个 Request 对象,该对象具有创建请求时的时间戳(触发 onkeyup 事件)并将其存储在全局数组 requests 。还有一个全局变量lastValidRequest,它存储实际修改DOM的最后一个Request对象的时间戳。在回调函数中,我检查时间戳是否小于 lastValidRequestRequest 并丢弃这些请求,因为它们比它们旧的和新的 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 JSONresponse 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

隐诗 2024-12-04 00:15:35

您需要做的是通过中止前一个连接来一次只允许一个连接。

不幸的是,我不太了解你的代码,无法了解这是如何完成的,但是使用常规 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 所做的那样。

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:

<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>

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文