I'm developing a chat in PhP and I'm doing long polling for check new messages on server. In Ajax request to do long polling the server checks for up 25 seconds if it has new registered messages. In that time when the server is arriving it does not return anything to the javascript and if I send a new request the browser waits for the checking to finish sending a new message
chat.js
function sndmessage(message, idchat) {
if (message != "") {
var $this = $('.chat .msgs');
var indice = 0;
var msg = message;
$('#sendmsg').val("");
$.ajax({
url: "../ajax/sendmessage.ajax.php",
type: "POST",
data: {
"message": msg,
"id": id
},
success: function(response) {
return;
}
});
}
return true;
}
function polling(idm, idu) {
var interval;
$.ajax({
async: true,
url: "../ajax/polling.ajax.php",
data: {
"idm": idm,
"idu": idu
},
type: "POST",
dataType: "JSON",
success: function(response) {
clearInterval(interval);
if (response.response == false) {
interval = setTimeout(function() {
polling(idm, idu);
}, 500);
} else {
if ('id' in response[0][0]) {
for (var i = 0; i < response[0].length; i++) {
if (mensagensIDs.indexOf(response[0][i]['id']) < 0) {
mensagensIDs.push(response[0][i]['id']);
let data = response[0][i]['data'].split(" "),
dia = data[0].split("-").reverse().join().replaceAll(",", "/"),
hora = data[1].split(":").slice(0, 2).join(":"),
mensagem = response[0][i]['mensagem'],
remetente = (response[0][i]['remetente'].indexOf(" - ") > 0) ? "admin" : "usuario",
destinatario = (response[0][i]['destinatario'].indexOf(" - ") > 0) ? "admin" : "usuario",
id = response[0][i]['id'];
let d = new Date();
let html = (d.getDate() == dia.split("/")[0]) ? hora : dia + " - " + hora;
chats.push({
"idu": idu,
"chat": {
"id": id,
"class": (remetente == "admin") ? "msg-adm teal lighten-1" : "msg-eu",
"class2": (remetente == "admin") ? "white-text" : "blue-text text-darken-2",
"msg": mensagem,
"tooltip": html,
"tooltippos": (remetente == "admin") ? "right" : "left"
}
});
if (idu == chatatual) {
$('.chat .msgs').append('<div id="' + idu + '" class="col s12">\
<div class="' + ((remetente == "admin") ? "msg-adm teal lighten-1" : "msg-eu") + ' z-depth-1">\
<span class="tooltipped pointer ' + ((remetente == "admin") ? "white-text" : "blue-text text-darken-2") + '" data-position="' + ((remetente == "admin") ? "right" : "left") + '" data-delay="50" data-tooltip="' + html + '">' + mensagem + '</span>\
</div>\
</div>').animate({
scrollTop: $('.msgs').prop("scrollHeight")
}, 500);
} else {
$('li.collection-item.avatar#' + idu).find('.badge').text("New message");
}
}
}
interval = setTimeout(function() {
polling(mensagensIDs[mensagensIDs.length - 1], idu);
}, 500);
} else {
interval = setTimeout(function() {
polling(idm, idu);
}, 5000);
}
}
}
});
}
I want know how to send a request without waiting for the other request
It's actually quite simple. What you're doing is sending the request and calling for the next loop when you get the response and that is not what you want. What you should do is something like:
function polling(idm,idu){
var interval;
$.ajax({/*do your stuff here*/});
setTimeout(function(){pooling(/*whatever*/)}, 500); // See that this is outside the ajax call, so it doesn't wait for the response
}
Why not set the both 'async' in ajax to true? You can send the second ajax without waiting for the first one.
$.ajax({
'async': true,
//your code
})
This kind of thing can be a total nightmare until you know how to work with promises .
The key here is to understand that :
jQuery.ajax()
returns a promise. jQuery.ajax()
against a promise that is guaranteed to reject after 25000 ms. Now, there are two ways to write the code (see footnote 2 for explanation)
using jQuery promises throughout
First two utility functions :
// a promise-returning `delay()` utility, which is the only place that `setTimeout()` is used.
function delay(t) {
return new jQuery.Deferred(function(dfrd) {
setTimeout(dfrd.resolve, t);
}).promise();
}
// a promise-returning `race()` utility which ensures that the first promise in `promises` to resolve/reject will resolve/reject the returned promise.
function race(promises) {
return new jQuery.Deferred(function(dfrd) {
promises.forEach(function(p) {
p.then(function(result) {
dfrd.resolve(result);
}, function(reason) {
dfrd.reject(reason);
});
});
}).promise();
}
Now, polling()
function polling(idm, idu) {
// first promise
var ajaxPromise = $.ajax({
'async': true,
'url': '../ajax/polling.ajax.php',
'data': { 'idm': idm, 'idu': idu },
'type': 'POST',
'dataType': 'JSON',
}).then(function(response) {
if (response.response && ('id' in response[0][0])) {
// ... lots of synchronous processing ...
return [mensagensIDs[mensagensIDs.length - 1], idu]; // or maybe `return [mensagensIDs.pop(), idu]`?
} else {
return [idm, idu];
}
});
// second promise
var timeoutPromise = delay(25000).then(function() {
return new jQuery.Deferred().reject(new Error('long-poll-timeout')).promise();
});
// Now the clever bit ...
// At this point you have two promises, which can be raced against each other.
// Exactly what happens next, depends on who wins the race.
// * if `timeoutPromise` wins the race, it will be caught below, the ajax will be aborted, then execution will progress to the second chained `.then()`.
// * if `ajaxPromise` wins the race, then the `.catch()` clause will be bypassed, and execution will progress directly to the second chained `.then()`.
return race([ajaxPromise, timeoutPromise])
.then(null, function(error) { // this is effectively a `.catch()` block.
console.log(error.message); // you will see 'long-poll-timeout' (or possibly some ajax/http error message).
ajaxPromise.abort(); // ensure that `ajaxPromise` **doesn't** follow its success path.
return [idm, idu]; // deliver `[idm, idu]` to the chained .then().
})
.then(function(args) { // via one route or other, `[idm, idu]` or `[mensagensIDs[mensagensIDs.length - 1], idu]` is delivered here as `args`.
return delay(500).then(function() {
return polling.apply(null, args);
});
});
}
using jQuery.ajax() and javascript native Promises
First, one utility function :
// a promise-returning `delay()` utility, which is the only place that `setTimeout()` is used.
function delay(t) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, t);
});
}
Now, polling()
function polling(idm, idu) {
// first promise
var ajaxPromise = $.ajax({
'async': true,
'url': '../ajax/polling.ajax.php',
'data': { 'idm': idm, 'idu': idu },
'type': 'POST',
'dataType': 'JSON',
}).then(function(response) {
if (response.response && ('id' in response[0][0])) {
// ... lots of synchronous processing ...
return [mensagensIDs[mensagensIDs.length - 1], idu]; // or maybe `return [mensagensIDs.pop(), idu]`?
} else {
return [idm, idu];
}
});
// second promise
var timeoutPromise = delay(25000).then(function() {
return Promise.reject(new Error('long-poll-timeout'));
});
// Now the clever bit ...
// At this point you have two promises, which can be raced against each other.
// Exactly what happens next, depends on who wins the race.
// * if `timeoutPromise` wins the race, it will be caught below, the ajax will be aborted, then execution will progress to the chained `.then()`.
// * if `ajaxPromise` wins the race, then the `.catch()` clause will be bypassed, and execution will progress directly to the chained `.then()`.
return Promise.race([ajaxPromise, timeoutPromise])
.catch(function(error) {
console.log(error.message); // you will see 'long-poll-timeout' (or possibly some ajax/http error message).
ajaxPromise.abort(); // ensure that `ajaxPromise` **doesn't** follow its success path.
return [idm, idu]; // deliver `[idm, idu]` to the chained .then().
})
.then(function(args) { // via one route or other, `[idm, idu]` or `[mensagensIDs[mensagensIDs.length - 1], idu]` is delivered here as `args`.
return delay(500).then(function() {
return polling.apply(null, args);
});
});
}
Notes:
timeout:
option but constraints in Firefox 3.0+ make that approach non-universal.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.