построение стека запросов JSONP - PullRequest
0 голосов
/ 01 августа 2011

Я создаю окно автоматической подсказки с API-интерфейсом Wikipedia и . Проблема в том, что порядок обновлений DOM основан на порядке ответов, полученных с сервера, тогда как на самом деле он должен зависеть от порядка запуска.onkeyup событие. , так что если я ищу Lady Gaga, и я нажимаю L, а затем a .now, если ответ на запрос, где я ищу L, приходит позже, чем ответ для La затем DOM обновляется ответом L, что не должно произойти, потому что мой самый последний ввод - La.

Поэтому при каждом событии onkeyup создается объект Request, который имеет метку временикогда запрос был создан (onkeyup событие сработало) и сохранить его в глобальном массиве requests.также есть глобальная переменная lastValidRequest, которая хранит метку времени последнего Request объекта, который фактически изменил DOM.В функции обратного вызова я проверяю, было ли отправлено 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 ссылка этого кода здесь


ОБНОВЛЕНИЕ

Я выяснил, как избежать неприятностей с 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
}

, но именно то, что я ищу, это

КАК Я АССОЦИИРУЮ АЗАПРОС С ОТВЕТОМ В ОБЩЕМ?

то есть как я могу решить, какой ответ принадлежит какому запросу ( Я за гипотезы? )

1 Ответ

3 голосов
/ 01 августа 2011

Что вам нужно сделать, это разрешить только одно соединение за раз, прервав предыдущее.

К сожалению, я недостаточно хорошо понял ваш код, чтобы увидеть, как это делается, но с обычным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 в моем примере.

...