how to transform function to setTimeout - javascript

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

How do I set a minimum time between the start of an ajax request and its success?

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);
}
}
}
});
}
}

Reusing a JavaScript AJAX call before another AJAX call

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.

Issues with jquery html()

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';)

query clearInterval when variable is "x"

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) {}

Ajax, prevent multiple request on click

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. :)

Categories