开发者

building a stack of JSONP requests

开发者 https://www.devze.com 2023-03-24 08:10 出处:网络
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

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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号