I'm using setInterval for now, but wish to use setTimeout.
$.when(
data['layout'] = "getMessages",
data['limit'] = limit,
fetchMsg(data,'[data-messages]',{"background-color":"#fff"})
).then(
setInterval(function(){
data['lastupdate'] = localStorage.lastupdate;
data['layout'] = "getNewMessages",
fetchMsg(data, '[data-body-new]',{"background-color":"#b4eeb4"});
}, 1000)
);
//the function
function fetchMsg(info, container, messageStyle){
$.ajax({
method: "POST",
url: window.root+"/index.php",
"data": info,
error: function() {
alert('error');
},
success: function(result) {
..........
}
});
I tried below but it doesn't work:
setTimeout(function(){
data['lastupdate'] = localStorage.lastupdate;
data['layout'] = "getNewMessages",
fetchMsg(data, '[data-body-new]',{"background-color":"#b4eeb4"});
}, 1000)
//the function
function fetchMsg(info, container, messageStyle){
$.ajax({
method: "POST",
url: window.root+"/index.php",
"data": info,
error: function() {
alert('error');
},
success: function(result) {
..........
},
complete:fetchMsg
});
I won't fix your code for you but here is a basic idea of going from an interval to a setTimeout.
Firstly, make your 'interval' equal to a variable.
var init = setInterval(doFunc,1000);
Later when you want to make the change:
clearInterval(init);
and then to set Timeout just do:
setTimeout(doFunc);
And thats basically it.
Related
Basically, sometimes the AJAX calls in my application are too fast and I need to delay some of them. I have a "progress/loading" icon and when it comes to the fast AJAX calls the icon appears and disappears too quickly. I need a way to set a minimum time for an AJAX action to finish (or at least to appear that way). Here's my generic ajax function that I use in my application.
var app = {
ajax: function (paramObject) {
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if (paramObject.successDelay) {
setTimeout(function() {
paramObject.success(jsonResponse);
}, paramObject.successDelay);
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
As you can see I have a paramObject which takes some parameters like: url, method, data, success and successDelay. Currently, the AJAX call takes its time and when it finishes it takes in consideration the delay (successDelay) that I've set. But that's not really what I wanted. What I want is to track the delay between the start of the AJAX call and its end/success so the whole thing takes a minimum of successDelay milliseconds.
EDIT to further explain:
In essence I want to make it seem as though the AJAX call takes longer. And it needs to happen in the function I have above.
[EDIT]
Without understanding your code, I think this is what you want :
var app = {
ajax: function (paramObject) {
var timeStart = Date.now();
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if ((Date.now()-timeStart) < paramObject.successDelay) {
setTimeout(function() {
paramObject.success(jsonResponse);
}, paramObject.successDelay - (Date.now()-timeStart));
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
Don't delay the AJAX, just check if you remove the waiting animation class with or without a delay :
// before the AJAX call
var timeStartMs = Date.now();
// On the success block, we check if more or less than 500ms
// and we remove the '.waiting' class
if(Date.now() < timeStartMs + 500)
setTimeout(function(){ $('.target').removeClass('waiting'); }, 500);
else
$('.target').removeClass('waiting');
Like this :
var timeStartMs;
function f() {
// before the AJAX call
var timeStartMs = Date.now();
var ping = Math.floor(Math.random() * 2000) + 1;
$('#target').addClass('waiting');
$('#target').html('Lag : '+ping);
// fake AJAX call :
setTimeout(function() {
if (Date.now() < timeStartMs + 500)
setTimeout(function() {
$('#target').removeClass('waiting');
}, 500);
else
$('#target').removeClass('waiting');
}, ping);
}
.waiting {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="target">Click</div>
<button onclick="f()">run</button>
I haven't tested it, but I believe it does what you want.
var app = {
ajax: function (paramObject) {
var $d;
if (paramObject.successDelay) {
$d = $.Deferred();
setTimeout(function() {
$d.resolve();
}, paramObject.successDelay);
}
$.ajax({
url: paramObject.url,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: paramObject.method || 'GET',
data: paramObject.data || '{}',
success: function (jsonResponse) {
if (paramObject.success) {
if (paramObject.successDelay) {
$d.done(function(){
paramObject.success(jsonResponse);
});
} else {
paramObject.success(jsonResponse);
}
}
}
});
}
}
I have two buttons that both performs AJAX call:
$("#save").click(function() {
$.ajax({
type: "POST",
url: saveEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
})
$("#tag-as-final").click(function() {
$.ajax({
type: "POST",
url: finalizeEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
})
The requirement is that when the user click the finalize button, the system will first perform a save before actually tagging it as final. To reuse the code attached to the save button, I call the onclick listener of the save button before the actual AJAX call like this:
$("#tag-as-final").click(function() {
$("#save").click()
^^^^^^^^^^^^^^^^^^
$.ajax({
type: "POST",
url: finalizeEntryURL,
But it will not do "save-and-finalize-after" behavior since both AJAX calls are asynchronous. I need to run one after another, but cannot afford to make the AJAX call of the save button synchronous (I'm doing also a lot of other things while the tagging occurs occurs). I know this would be silly but I'm thinking something similar to...
$("#tag-as-final").click(function() {
$("#save").click().peformAsyc()
^^^^^^^^^^^^
$.ajax({
type: "POST",
url: finalizeEntryURL,
...that will force it to finish performing first the chained function before continuing, but I know that is not available. Is there any way to do this? My current work-around is placing the same save AJAX function inside the finalize AJAX function, though it doesn't allow me to code DRY (Don't Repeat Yourself):
$("#tag-as-final").click(function() {
$.ajax({
type: "POST",
url: saveEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
$.ajax({
type: "POST",
url: finalizeEntryURL,
data: { id: $("#id").val() },
success: function(r) {
...
},
error: function(r) {
...
}
})
},
error: function(r) {
...
}
})
})
It's pretty simple, you are better using jquery "promises". Like so:
var generalSettings = { }; //Settings for AJAX call.
var jqXHR = $.ajax(generalSettings); //Do AJAX call.
generalSettings.data = 'newdata'; //update generalSettings
jqXHR.done(function(data){
$.ajax(generalSettings); //New Petition with updated settings.
});
This is using ES6 promises and jQuery promises:
function doAjaxAsPromise(settings){
return new Promise(function(resolve){
var jqXHR = $.ajax(settings);
jqXHR.done(function(data){
resolve(data);
});
});
}
var settings = { };
var petition = doAjaxAsPromise(settings);
var secondpetition = petition.then(function(data){
//work with data
//new settings
var settings = { };
return doAjaxAsPromise(settings);
});
var thirdpetition = secondpetition.then(function(data){
//work with data
//new settings
var settings = { };
return doAjaxAsPromise(settings);
});
//If needed to reuse settings object outside promise scope:
//var settings = Object.create(settings);
Some other nice thing you can do for code reuse:
function save(settings) {
var prom = doAjaxAsPromise(settings);
return prom.then(function(data){
//do something with your data.
});
}
function tagAsFinal(savedPromise, settings){
return savedPromised.then(function(){
var prom = doAjaxAsPromise(settings);
return prom.then(function(data){
//work with data;
});
});
}
$('save').on('click', function(){
save(settings); //settings = $.ajax settings.
});
$('tagAsFinal').on('click', function(){
var generalSettings = { };
var settingsone = Object.create(generalSettings);
var settingstwo = Object.create(generalSettings);
var saved = save(settingsone); //$.ajax settings.
tagAsFinal(saved, settingstwo);
});
//Can still be reduced.
Having some issues properly getting the manipulated data from an element.
Everywhere on the internet doesn't seem to cover such a simple question with a simple answer. Please help.
I have manipulated an element with a returning ajax request:
$("#last_comment_added").html("1457856458")
now my function on the page:
jQuery(document).ready(function($) {
var post_slug = $("#post_slug").html();
var last_comment_added = $("#last_comment_added").text();
if (post_slug && last_comment_added) {
setInterval(function() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": last_comment_added
},
cache: false,
success: function(html) {
eval(html)
}
});
}, 10000);
}
});
I get the old data from the element, not the new ajax "1457856458" data.
Please help.
If I understand your problem right it's just that you create this variable called last_comment_added and expect it to be continually updated, you set it once to be the text of the last_comment_added, it's never updated in your interval function. Here's a change that should make it work better for you.
jQuery(document).ready(function($) {
var post_slug = $("#post_slug").html();
if (post_slug && last_comment_added) {
setInterval(function() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": $("#last_comment_added").text()
},
cache: false,
success: function(html) {
eval(html)
}
});
}, 10000);
}
});
Don't use eval.
Try
$(document).ready(function() {
var post_slug = $("#post_slug").html();
var last_comment_added = $("#last_comment_added").html();
if (post_slug && last_comment_added) {
setInterval(_update, 10000);
}
});
function _update() {
$.ajax({
type: "POST",
url: "ajax_comments.php",
data: {
"task": "updates",
"post_slug": post_slug,
"last_comment_added": last_comment_added
},
cache: false,
success: function(data) {
$("#last_comment_added").html(data)
}
});
}
and you return from PHP only NEW data. (something like: echo '1457856458';)
I have made a function that is controlling a row in a my database for a certain number with AJAX.
Im calling the function with a click function and putting the function in a setInterval function to make the check 10 times a second.
In the beginning it will return 0, but at some point (usually within 5 seconds) it will return something els than 0, when it does i want to clearInterval.
But im not sure how to this?
This is my function:
function get_buzzer() {
$.ajax({
url: 'ajax_buzzer.php',
dataType: 'json',
async: false,
type: 'post',
data: {
job: 'get'
},
success:function(s) {
if(s['number'] == 0) {
var player = false;
} else {
var player = true;
}
}, error:function(e) {
}
});
}
$(document).ready(function() {
$('#test').click(function() {
var buzzer = setInterval("get_buzzer()",100);
});
});
You can do something like
$(document).ready(function () {
//make buzzer a share variable
var buzzer;
$('#test').click(function () {
buzzer = setInterval(get_buzzer, 100);
});
function get_buzzer() {
$.ajax({
url: 'ajax_buzzer.php',
dataType: 'json',
async: false,
type: 'post',
data: {
job: 'get'
},
success: function (s) {
if (s['number'] != 0) {
//if number is not 0 then clear the interval
clearInterval(buzzer)
}
},
error: function (e) {}
});
}
});
Try this : declare global variable to store interval and call window.clearInterval in success call of ajax
var buzzer;
function get_buzzer() {
$.ajax({
url: 'ajax_buzzer.php',
dataType: 'json',
async: false,
type: 'post',
data: {
job: 'get'
},
success:function(s) {
if(s['number'] == 0) {
var player = false;
} else {
var player = true;
//clear interval
window.clearInterval(buzzer);
}
}, error:function(e) {
}
});
}
$(document).ready(function() {
$('#test').click(function() {
buzzer = setInterval("get_buzzer()",100);
});
});
Use:
inside success use: And make var buzzer Gloval var.
clearInterval(buzzer);
Refence
You just need to clear the interval in the success handler of ajax call over a condition.
success: function (s) {
if (s['number'] != 0) {
//if number is not 0 then clear the interval
clearInterval(buzzer)
}
},
error: function (e) {}
I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..
$('#do-login').click(function(e) {
e.preventDefault();
if ( $(this).data('requestRunning') ) {
return;
}
$(this).data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
});
Any ideas? Thanks!
The problem is here:
complete: function() {
$(this).data('requestRunning', false);
}
this no longer points to the button.
$('#do-login').click(function(e) {
var me = $(this);
e.preventDefault();
if ( me.data('requestRunning') ) {
return;
}
me.data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
me.data('requestRunning', false);
}
});
});
Use on() and off(), that's what they are there for :
$('#do-login').on('click', login);
function login(e) {
e.preventDefault();
var that = $(this);
that.off('click'); // remove handler
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize()
}).done(function(msg) {
// do stuff
}).always(function() {
that.on('click', login); // add handler back after ajax
});
});
In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this, //<-----
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
You can disable the button.
$(this).prop('disabled', true);
I have also faced a similar problem.
Just adding $('#do-login').attr("disabled", true); gives me the solution.
$('#do-login').click(function(e) {
e.preventDefault();
$('#do-login').attr("disabled", true);
.........
.........
Here do-login is button id.
I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,
var settings = {
"url": "/php/auth/login.php",
"method": "POST",
"timeout": 0,
"async": false,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
try{
console.log(ress, "Result from Ajax here");
}
catch(error){
alert(error);
console.log(ress);
}
});
async : false worked for me.
Thanks.
Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.
// CSS
.disabled{
cursor: not-allowed;
}
// JQUERY
$('#do-login').click(function(e) {
e.preventDefault();
$(this).addClass("disabled");
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this,
success: function(msg) {
//do more here
$(this).removeClass("disabled");
},
});
});
P.S. If you use bootstrap css, you do not need the css part.
I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.
export default function (button, promise) {
const $button = $(button);
const semaphore = 'requestRunning';
if ($button.data(semaphore)) return null;
$button.data(semaphore, true);
return promise().always(() => {
$button.data(semaphore, false);
});
}
Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.
Roughly speaking, here's the usage.
import preventDoubleClick from './preventdoubleclick';
...
button.click(() => {
preventDoubleClick(this, () => $.ajax()
.done(() => { console.log("success") }));
});
This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)
var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
var a = this;
a.Start_Request = function(){
if(window.Requests == undefined){
window.Requests = {};
}
window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
}
a.End_Request = function(){
if(window.Requests == undefined){
window.Requests = [];
}
window.Requests[Request_Name] = undefined;
}
a.Is_Request_Running = function(){
if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
return 0;
}else{
var Time = + new Date();
// Reactivate the request flag if server take more than 10 sec to respond
if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout))
{
return 0;
}else{
return 1
}
}
}
}
To use it:
var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){
Request_Flag.Start_Request();
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
Request_Flag.End_Request();
}
});
}
for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:
Use window.onload = function() { ... }
instead of
$(document).ready(function(){ ... });
on the main index.php page. Its will be prevent all multi request. :)