Reputation: 4742
I have an input field. Whenever there's change in the text in the input field, I make an ajax call to process.php
I need to handle all the responses. But some responses come early, whereas some come late, depending on the input. So the order of responses is not same as order of making ajax calls.
So right now I'm doing it by setting async: false
But I don't want the client side to be stuck due to async: false
$("#text_input").on("input", function() {
var password = $("#text_input").val();
var length = password.length;
$.ajax({
url: "process.php",
type: "POST",
async: false,
data: {
password: $(this).val()
}
}).done(function (data) {
console.log(data);
console.log(password + " : " + length);
}).fail(function( jqXHR, textStatus, errorThrown ) {
alert( "Request failed: " + textStatus + " , " + errorThrown );
});
});
I tried looking in promises, but did not understand whether it can be applied here.
How can I execute responses in order?
Upvotes: 4
Views: 5590
Reputation: 106
The problem with async is exactly that, that is asynchronous, that means that the code runs without waiting to finish. Therefore all your requests go to the server and once they start returning your code catches them and executes them.
If you want to handle them in order, you will need to build a queue and the code to handle the queue.
You should then assign an ordered number to all your requests which should then come in the response (so you know the proper order of the response).
Then you can add the response to the queue, and call a method which processes the queue, but that method only processes the queue in order, meaning that it only processes responses starting from 0, 1, 2, 3 etc... so if in the queue there is a result 5 and not a result 0, the queue won't be processed, the queue will be processed only if result 0 is there and so on...
Here is an example code, I haven't tested it but should work or at least should give you an idea on how to start :)
var currentOrder = 0;
var queue = [];
function processQueue() {
// Sort the queue
queue.sort(function(a, b) {
var aOrder = a.order;
var bOrder = b.order;
if (aOrder < bOrder) {
return -1;
}
if (aOrder > bOrder) {
return 1;
}
// Order is equal (this shouldn't happen)
return 0;
});
if (queue[0].order === currentOrder) {
doSomething(data);
queue.splice(0, 1); // Remove the first item from the queue as it's already processed
currentOrder++;
processQueue(); // Process the queue again
}
}
// Do something with the data
function doSomething(data) {
console.log(data);
}
$('#text_input').on('input', function() {
$.ajax({
url: 'process.php?order=' + order, // We send the order to the backend so it can be returned in the response
type: 'POST',
data: {
password: $(this).val()
}
}).done(function(data) {
// Data should contain the order somewhere, let's say for example it's a json and it's inside data.order
queue.push(data);
processQueue();
});
});
Upvotes: 2
Reputation: 91792
Assuming that you are only interested in the results of the latest ajax call, you can assign the value returned from the $.ajax call - a jqXHR object - to a variable and then abort the request when a new one is fired.
Something like:
var request = null;
$("#password_input").on("input", function() {
var password = $("#password_input").val();
var length = password.length;
// you can also check the type of the variable, etc.
if (request) {
request.abort();
}
request = $.ajax({
url: "process.php",
type: "POST",
...
Upvotes: 1
Reputation: 275
Why not use setTimeout function
to whenever they press some letter on your input field. you can do it just like this:
setTimeout(function(){
$.ajax({
url: "process.php",
type: "POST",
data: {
password: $(this).val()
}
}).done(function (data) {
console.log(data);
console.log(password + " : " + length);
}).fail(function( jqXHR, textStatus, errorThrown ) {
alert( "Request failed: " + textStatus + " , " + errorThrown );
});
}, 1000);
This is to setTimeout once the press on your input field and wait 1sec then when finished type on the input field it will generate the ajax after 1sec.
Upvotes: 0