running-coder / jquery-typeahead

Javascript Typeahead (autocomplete) plugin with more than 50 options and callbacks.
http://www.runningcoder.org/jquerytypeahead/
MIT License
543 stars 121 forks source link

Stops calling ajax requests after a bit #20

Closed ldrrp closed 9 years ago

ldrrp commented 9 years ago

Unsure why, its intermitent and i have not been able to 100% replicate it.

While searching using the dynamic option. sometimes it just stops running anymore ajax calls.

running-coder commented 9 years ago

hey ldrpp,

could you paste me your typeahead html and javascript initialization? I'll verify with the options you have

Thanks

ldrrp commented 9 years ago
<div class="search-navigation col-xs-12">
    <form class="clearfix" action="search">
        <div class="typeahead-container form-group col-xs-12">
            <div class="typeahead-field">
                <span class="typeahead-query">
                    <input class="form-control" id="search-field" name="q" type="search" placeholder="e.g. 1685 Elmwood Ave Buffalo, NY 14207" autocomplete="off">
                </span>
            </div>
        </div>
    </form>
</div><!-- /.search-navigation -->
$(document).ready(function(){
$('#search-field').typeahead({
        maxItem: 12,
        minLength: 2,
        order: null,
        dynamic: true,
        accent: true,
        source: {
            zipcode: {
                url: [
                    {
                        type: "POST",
                        url: "/includes/send/index/search.php",
                        data: { search: "{{query}}" }
                    },
                    "data"
                ]
            }
        },
        selector: {
            dropdown: "dropdown-menu",
            list: "dropdown-menu"
        },
    });
});

service side json response with data

{
    "status": true,
    "error": null,
    "data": [
        "601 N St, Elmont NY",
        "601 N St, Glen Oaks NY",
        "601 N St, Floral Park NY",
        "601 W N 00 S, Marion IN",
        "601 E N 00 S, Marion IN",
        "601 W N 00 S, Swayzee IN",
        "601 E N 10th St, Albany TX",
        "601 W N 00 S 27, Converse IN",
        "601 W N 1st St, Strasburg IL",
        "601 E N 1st St, Strasburg IL"
    ]
}

service side json response with no data

{
    "status": false,
    "error": null,
    "data": []
}
ldrrp commented 9 years ago

Demo: https://dev.usfoodorder.com/

running-coder commented 9 years ago

hey ldrrp,

I think I know whats happening and it is indeed an issue. I am currently in the process of writing the version 2.0 and will note this issue.

I've noted when looking at your source that you have async scripts loading. This is very dangerous because file 3 ca finish loading and execute before the file 1. In the screenshot I've taken that issue happened and it gave me a JS error async scripts. I would recommend removing the async attribute or looking at the defer attribute (not sure if defer preserves the script order).

Thanks for the feedback, the version 2.0 should be out within a couple days.

ldrrp commented 9 years ago

Thanks for catching that, ill fix that soon. But i don't think that's the problem. It does load before the section of code is called on my computer since its probably cached.

running-coder commented 9 years ago

Hey ldrrp,

you are right, the issue is on my side between the time the request is sent and received. If a new request is sent in between it starts failing.

Happy path: char typed -> options.delay -> request sent -> request received -> request parsed

Error path: char typed -> options.delay -> 1st request send -> char typed -> 2nd request sent -> 1st request received -> 2nd request received -> (not sure which is parsed afterwards)

Meaning there is an issue with the internal request queue system. I'll take a look what is wrong and fix it in the 2.0.

coenier commented 9 years ago

This feels like a show stopper currently. For a work around i have changed my delay to 1000

running-coder commented 9 years ago

The development of 2.0 is close to complete, it seemed to me that the easiest and more efficient way to fix this issue was to abort previous requests if a new one is made.

https://github.com/running-coder/jquery-typeahead/blob/prototype-pattern(v2.0)/jquery.typeahead.2.js#L392

I'll update this ticket once there is a first RC for you guys to test with.

ldrrp commented 9 years ago

@running-coder Is everything ok, I noticed the website is down. I can sponsor hosting as well as a donation to keep the domain active.

running-coder commented 9 years ago

@ldrrp Hey Thanks for noticing! Somehow I've missed the domain expiry notifications. The site should be back soon and thanks for the offer.

Regarding your Ajax issue, you can start testing the newest Typeahead version 2.0 https://github.com/running-coder/jquery-typeahead/tree/prototype-pattern(v2.0)

lots of new features and fixed issues from the previous version. Unfortunately the website documentation is not up to date yet and I still have to code few more example on how to use the 2.0 features but for your case it should resolve the dynamic option issue without changing your init configuration.

let me know!

Thanks

ldrrp commented 9 years ago

@running-coder Seems to be working fine with 2.0 running. I will let you know if i notice the issue again.

ldrrp commented 9 years ago

@running-coder Seems like im having another issue now. I believe you are ending the running jquery call but its triggering my bind that i have set to pickup on failed ajax calls so i can redirect users to an error page. Is there someway you can kill the call without getting a bad response status. Or maybe you can help me modify this to exclude a force aborted call.

$(document).bind("ajaxError ajaxComplete", function(e,response,object2){
    if(     
        response.status != 200 && 
        response.status != 201 && 
        response.status != 202 && 
        response.status != 301 && 
        response.status != 302
    ){
        var port = window.location.port;
        if(window.location.port != ""){
            port = ":"+port;
        }
        window.location.href = window.location.protocol+"//"+window.location.hostname+"/error?code="+response.status;
    }
});
running-coder commented 9 years ago

Hey ldrrp,

on my side, aborting the previous request is the most efficient and simple way I can think of to handle dynamic requests that may conflict each others. I've replaced a whole queue system by 5 lines of code.

I've verified the error and response given by an Ajax.abort(). Aborting gives a status:0 so you can use that to filter out the Typeahead request from your function


$(document).bind("ajaxError ajaxComplete", function (e, response, ajaxObject) {
    if (!~[200, 201, 202, 301, 302].indexOf(response.status)) {

        if (!response.status && ajaxObject.url === '/includes/send/index/search.php') {
            // Abort request from Typeahead
            return;
        }

        // ... regular code here

    }
});
ldrrp commented 9 years ago

ive added checks for 0 to my script, thanks