I'm using jquery to call some javascript functions with a delay between them.
Also I'm using Jquery Wait
When I call below function,all functions are called recpectively,there are no delays between each other.
$(this)
.call(f1)
.wait(5000)
.call(f2)
.wait(5000)
.call(f3);
Here call function calls some function as I did
$.fn.call = function (f) {
if (f)
f();
return this;
};
What am i doing wrong ?
How can i achieve something like this ?
Thank you
If you want to call a function every 5 seconds use
setTimeout(function(){f1},5000);
setTimeout(function(){f2},10000);
setTimeout(function(){f2},15000);
if you want to call each function 5 seconds after the last one terminated use
setTimeout(function(){f1;setTimeout(function(){f2;setTimeout(function(){f3},5000);},5000);},5000);
You don't need wait() from that cookbook; delay() is built-in and appears to have the same functionality. But either function involves adding something to jQuery's internal queue of effects and then removing it after a timeout expires, i.e. it's not a sleep statement, so it's not going to wait around before returning.
If you want to use delay() or wait(), you should make call() enqueue the function with queue(). Just sketching, but something like:
$.fn.call = function(f) {
if (f) {
$(this).queue(function() {
f();
$(this).dequeue();
}
}
return this;
}
Then I'd expect your code to work the way you intend.
Here is a function that calls in sequence an array of function:
$.fn.callFn = function(fns, delay) {
var fn, that = this;
if(fns.length > 0){
fn = fns.shift()
fn && fn();
setTimeout(function(){
that.callFn(fns, delay);
}, delay);
}
return this;
};
And you would call it like that:
$(this).callFn([f1, f2, f3], 2000);
$('#box').slideUp(300).delay(800).fadeIn(400);
/* .delay = wait time = 800 (this means it will wait 800/1000 of a second/ "1000 = 1 second") */
Related
Let's say I have multiple functions func1, func2, func3, etc.....
And they all contain an AJAX/async function within them:
function funcX(){
// some ajax request
}
If in a main function I am calling func1, func2, func3 sequentially like so:
$(document).ready(function(){
func1();
func2();
func3();
...
}
Will each ajax/async function's call be certain to execute in the order of their parent functions? At first I thought they might be, but the behavior of my program seems to be suggesting otherwise...
If not, is there a good (hopefully simple?) alternative to having a long chain of callbacks?
Will each ajax/async function's call be certain to execute in the order of their parent functions?
They should execute in order, but their internal callbacks can be called in any order.
If not, is there a good (hopefully simple?) alternative to having a long chain of callbacks?
You could use a promise, and execute the next function when the promise has been resolved.
This example uses jQuery...
var fn1 = function () {
var d = $.Deferred();
setTimeout(function () {
$("body").text("Callback 1 done.") && d.resolve();
}, Math.random() * 1300 + 800);
return d.promise();
};
var fn2 = function () {
var d = $.Deferred();
setTimeout(function () {
$("body").text("Callback 2 done.") && d.resolve();
}, 500);
return d.promise();
};
$.when(fn1(), fn2()).then(function () {
setTimeout(function () {
$("body").text("All done.");
}, 300);
});
jsFiddle.
We use $.when() and pass the invoked functions we want to execute to it. We then use then() to show a final message (I placed a setTimeout() here so you can see the last resolved function's message in the document).
Each of these functions have their own deferred object which return the promise. A setTimeout() mocks an XHR for example's sake. When this callback is executed, we resolve the deferred object.
Once both have been deferred, we reach the callback for then().
To serialize tasks, I've written a helper function, which can also be found in my earlier answer:
function serializeTasks(arr, fn, done)
{
var current = 0;
fn(function iterate() {
if (++current < arr.length) {
fn(iterate, arr[current]);
} else {
done();
}
}, arr[current]);
}
It takes an array of values (in your case those are actually functions), a loop function and a completion handler. Below is the loop function:
function loopFn(nextTask, fn)
{
fn(nextTask);
}
It accepts an intermediate completion function as the first argument and each element of the aforementioned array.
To set everything in motion:
serializeTasks([func1, func2, func3], loopFn, function() {
console.log('all done');
});
Your functions are called with a single argument which should be passed to the AJAX success callback, e.g.
func1(nextTask)
{
$.ajax({
...,
success: nextTask
});
}
The order in which the asynch results are returned is not deterministic, and may wary every time.
func2 might complete before func1 etc
It is important to ensure correct order of execution. One pattern is to call the next function in the success callback of the prior function
Ex:
$.get("/someUrl",function(){
$.get("/nextAjaxCall", function(){
.....
});
});
If the dependency chain is very simple, I don't think it's necessary to introduce a framework to handle this
Or look at async library and it's awesomeness !
async
I have multiply functions with parameters simplified as:
function f1(p1,p2){
alert('Function one is P1:'+p1+' P2:'+p2);
}
function f2(p1,p2){
alert('Function two is P1:'+p1+' P2:'+p2);
}
I need to fire these is a sequence with a delay between. I have however found that jQuery dislikes running functions with parameters. I have tried the .click function.
$.delay(1000).click(f1('One',false)).delay(1000).click(f2('One',false));
But the delay makes the click functions not work...
I would just use a simple timeout:
f1("one", false);
setTimeout(function() { f2("one", false); }, 1000);
$.delay(1000).click(function(){f1('One',false);}).delay(1000).click(function(){f2('One',false);});
not sure what the click is for though ...
if you want to delay a function call then a much simpler way is to use setTimeout().
eg:
// calling it in a nested setTimeout for sequential delayed execution
setTimeout(function(){
f1('One',false);
setTimeout(function(){
f1('One',false)
},300)
},300)
function fn1()
{
alert(1);
}
function fn2()
{
alert(2);
}
var arr=[fn1,fn2];
var len=arr.length;
var time=1000;
for(var k=0;k<len;k++)
{
(function(k)
{
setTimeout(arr[k],time);
}(k))
time=time*2;
}
It executes after a delay of 1 second!
DEMO
using jQuery... how do I run a function and then run a second function every 2 minutes after.
eg:
function 1: runs once
function 2: runs every 2 minutes after function 1 has finished
Any help will be much appreciated.
C
function f2(){}
function f1(){
... some code ...
setInterval(f2, 2000*60);
}
//From somewhere in your code, call f1
f1();
setInterval also returns a handle which can be used to cancel further calling of that function.
jQuery's delay() function is not a replacement for javascript's setInterval or setTimeout. To run a function #1 once on page load and then function #2 every 2 minutes after:
function funcOne() {
// some javascript
setInterval('funcTwo()', 1000*60*2);
};
function funcTwo() {
// some other javascript
};
$(document).ready(function() {
funcOne();
});
Remember, you are using JQuery because it makes javascript more simple. JQuery is a javascript library, not a language, wich means you can perfectly use javascript functions on it.
For your problem, you only need to call, with the setTimeout, your second function, and put inside this function another setTimeout(ms);
Like this:
function f1(/*...*/){}
var t = setTimeout("f2()",2 * 60 * 1000);
And at the end of your f2() function you should include another setTimeout, in order to call that function every 2 minutes.
function f2(/*...*/){
//...
t = setTimeout("f2()",2 * 60 * 1000);
}
To cancel this callings to f2() is just as simple: clearTimeout(t);
I would rather use setTimeout(). It is supposed to be less demanding on the browser, more processor efficient.
Here's what your functions should look like:
function f2(){
t = setTimeout(f2, 2000 * 60);
// code for f2
}
function f1(){
// code for f1
setTimeout(f2, 2000 * 60);
}
Then wherever it is you want the whole thing to start, call the first function:
var t;
f1();
You can stop the loop anytime:
clearTimeout(t);
Be sure to trigger setTimeout at the beginning of f2, so that it fires exactly every 2 minutes. Any code before 'setTimeout', taking 'x' time to process would result in the next f2 call firing after 2min+x.
Heloo
if i get you right then this is a solution
function func1()
{}
function func2()
{}
window.onload = function()
{
func1();
var flag_first_call_is_after_2=0;
var interv = setInterval(
function()
{
if(flag_first_call_is_after_2==0)
{
flag_first_call_is_after_2=1;
}
else
{
func2();
}
}
,120000
);
}
99 times out of 100, this works perfectly:
function a(){
setInterval("b()",1000);
updateText("still working");
}
function b(){
timer++;
updateText(timer);
}
Occasionally the first loop waits for 20 seconds to 2 minutes. Thereafter it runs perfectly. I know the timer can pause on Android phones (when the soft keyboard is shown). Are there other conditions that might delay setInterval?
Firstly, it is strongly advised you provide a callback(function) as the first argument and not a string, because that string is evaluated in the global scope and we all know that bad things happen when we use eval in js (related eval post : When is JavaScript's eval() not evil?).
So, your
setInterval("b()", 1000);
should be rewritten as :
setInterval(b, 1000);
or:
setInterval(function() { b(); }, 1000);
I also recommend you use setTimeout to simulate a setInterval.
The main downfall of the setInterval function is that it executes a block of code every n milliseconds, regardless of the execution of the previous block of code.
So if for some reason a setInterval callback takes longer to execute than the delay provided, it will cause some stack overflows.
Let's take the following code for example :
function foo() {
// this takes about 2 seconds to execute
// .. code here
}
setInterval(foo, 1000);
This will actually freeze the browser because it will execute foo for an (almost) infinite number of times but it will never finish it.
The solution in this kind of case is to emulate the setInterval with setTimeout, in order to ensure that the callback has finished to execute before calling it again:
function foo() {
// this takes about 2 seconds to execute
// .. code here
}
function newSetInterval(callback, duration, callbackArguments) {
callback.apply(this, callbackArguments);
var args = arguments,
scope = this;
setTimeout(function() {
newSetInterval.apply(scope, args);
}, duration);
}
newSetInterval(foo, 1000);
Now, foo is called again only after the previous instance has finished the code execution.
I would apply the same thing to your code, in order to let the browser decide when it can execute the code, and not to force it to execute the block of code weather it's busy at that moment or not:
function a() {
newSetInterval(b, 1000);
updateText("still working");
}
function b() {
timer++;
updateText(timer);
}
function newSetInterval(callback, duration, callbackArguments) {
callback.apply(this, callbackArguments);
var args = arguments,
scope=this;
setTimeout(function() {
newSetInterval.apply(scope, args);
}, duration);
}
If you're interested, I've rewritten the setInterval and clearInterval functions in order to use them anywhere, without taking care of stack overflows :
function setInterval(f, time) {
setInterval.ids = setInterval.ids || {};
setInterval.idCount = setInterval.idCount || 0;
var that = this,
id = setInterval.idCount++,
// to prevent firefox bug that adds an extra element to the arguments
l = arguments.length - 2;
(function theFn() {
// to prevent firefox bug that adds an extra element to the arguments
var args = [].slice.call(arguments, 0, l);
f.apply(this, args);
setInterval.ids[id] = setTimeout.apply(this, [theFn, time].concat(args));
}).apply(that, [].slice.call(arguments, 2, arguments.length));
return id;
}
function clearInterval(id) {
if(!setInterval.ids || !setInterval.ids[id]) {
return false;
}
clearTimeout(setInterval.ids[id]);
return true;
}
try this,
setInterval(b, 1000);
or
setInterval(function(){
timer++;
updateText(timer);
}, 1000);
It's there a way to configure the setInterval method of javascript to execute the method immediately and then executes with the timer
It's simplest to just call the function yourself directly the first time:
foo();
setInterval(foo, delay);
However there are good reasons to avoid setInterval - in particular in some circumstances a whole load of setInterval events can arrive immediately after each other without any delay. Another reason is that if you want to stop the loop you have to explicitly call clearInterval which means you have to remember the handle returned from the original setInterval call.
So an alternative method is to have foo trigger itself for subsequent calls using setTimeout instead:
function foo() {
// do stuff
// ...
// and schedule a repeat
setTimeout(foo, delay);
}
// start the cycle
foo();
This guarantees that there is at least an interval of delay between calls. It also makes it easier to cancel the loop if required - you just don't call setTimeout when your loop termination condition is reached.
Better yet, you can wrap that all up in an immediately invoked function expression which creates the function, which then calls itself again as above, and automatically starts the loop:
(function foo() {
...
setTimeout(foo, delay);
})();
which defines the function and starts the cycle all in one go.
I'm not sure if I'm understanding you correctly, but you could easily do something like this:
setInterval(function hello() {
console.log('world');
return hello;
}(), 5000);
There's obviously any number of ways of doing this, but that's the most concise way I can think of.
I stumbled upon this question due to the same problem but none of the answers helps if you need to behave exactly like setInterval() but with the only difference that the function is called immediately at the beginning.
Here is my solution to this problem:
function setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
The advantage of this solution:
existing code using setInterval can easily be adapted by substitution
works in strict mode
it works with existing named functions and closures
you can still use the return value and pass it to clearInterval() later
Example:
// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
console.log('hello');
}, 1000);
// clear interval after 4.5 seconds
setTimeout( _ => {
clearInterval(myInterval);
}, 4500);
To be cheeky, if you really need to use setInterval then you could also replace the original setInterval. Hence, no change of code required when adding this before your existing code:
var setIntervalOrig = setInterval;
setInterval = function(func, interval) {
func();
return setIntervalOrig(func, interval);
}
Still, all advantages as listed above apply here but no substitution is necessary.
You could wrap setInterval() in a function that provides that behavior:
function instantGratification( fn, delay ) {
fn();
setInterval( fn, delay );
}
...then use it like this:
instantGratification( function() {
console.log( 'invoked' );
}, 3000);
Here's a wrapper to pretty-fy it if you need it:
(function() {
var originalSetInterval = window.setInterval;
window.setInterval = function(fn, delay, runImmediately) {
if(runImmediately) fn();
return originalSetInterval(fn, delay);
};
})();
Set the third argument of setInterval to true and it'll run for the first time immediately after calling setInterval:
setInterval(function() { console.log("hello world"); }, 5000, true);
Or omit the third argument and it will retain its original behaviour:
setInterval(function() { console.log("hello world"); }, 5000);
Some browsers support additional arguments for setInterval which this wrapper doesn't take into account; I think these are rarely used, but keep that in mind if you do need them.
Here's a simple version for novices without all the messing around. It just declares the function, calls it, then starts the interval. That's it.
//Declare your function here
function My_Function(){
console.log("foo");
}
//Call the function first
My_Function();
//Set the interval
var interval = window.setInterval( My_Function, 500 );
There's a convenient npm package called firstInterval (full disclosure, it's mine).
Many of the examples here don't include parameter handling, and changing default behaviors of setInterval in any large project is evil. From the docs:
This pattern
setInterval(callback, 1000, p1, p2);
callback(p1, p2);
is identical to
firstInterval(callback, 1000, p1, p2);
If you're old school in the browser and don't want the dependency, it's an easy cut-and-paste from the code.
I will suggest calling the functions in the following sequence
var _timer = setInterval(foo, delay, params);
foo(params)
You can also pass the _timer to the foo, if you want to clearInterval(_timer) on a certain condition
var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);
For someone needs to bring the outer this inside as if it's an arrow function.
(function f() {
this.emit("...");
setTimeout(f.bind(this), 1000);
}).bind(this)();
If the above producing garbage bothers you, you can make a closure instead.
(that => {
(function f() {
that.emit("...");
setTimeout(f, 1000);
})();
})(this);
Or maybe consider using the #autobind decorator depending on your code.
You can set a very small initial delay-time (e.g. 100) and set it to your desired delay-time within the function:
var delay = 100;
function foo() {
console.log("Change initial delay-time to what you want.");
delay = 12000;
setTimeout(foo, delay);
}
To solve this problem , I run the function a first time after the page has loaded.
function foo(){ ... }
window.onload = function() {
foo();
};
window.setInterval(function()
{
foo();
}, 5000);
This example builds on #Alnitak's answer, but uses await Promise for finer granularity of control within the loop cycle.
Compare examples:
let stillGoing = true;
(function foo() {
console.log('The quick brown fox did its thing');
if (stillGoing) setTimeout(foo, 5000);
})();
foo();
In the above example we call foo() and then it calls itself every 5 seconds.
But if, at some point in the future, we set stillGoing to false in order to stop the loop, we'll still get an extra log line even after we've issued the stop order. This is because at any given time, before we set stillGoing to false the current iteration will have already created a timeout to call the next iteration.
If we instead use await Promise as the delay mechanism then we have an opportunity to stop the loop before calling the next iteration:
let stillGoing = true;
(async function foo() {
console.log('The quick brown fox did its thing');
await new Promise(resolve => setTimeout(resolve, 5000));
if (stillGoing) foo();
})();
foo();
In the second example we start by setting a 5000ms delay, after which we check the stillGoing value and decide whether calling another recursion is appropriate.
So if we set stillGoing to false at any point, there won't be that one extra log line printed after we set the value.
The caveat is this requires the function to be async, which may or may not be an option for a given use.
For Those using React, here is how I solve this problem:
const intervalRef = useRef(0);
useEffect(() => {
if (condition is true){
if (intervalRef.current === 0) {
callMyFunction();
}
const interval = setInterval(() => {
callMyFunction();
}, 5_000);
intervalRef.current = interval;
} else {
clearInterval(intervalRef.current);
}
}, [deps]);
// YCombinator
function anonymous(fnc) {
return function() {
fnc.apply(fnc, arguments);
return fnc;
}
}
// Invoking the first time:
setInterval(anonymous(function() {
console.log("bar");
})(), 4000);
// Not invoking the first time:
setInterval(anonymous(function() {
console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
console.log("baz");
}, 4000);
Ok this is so complex, so, let me put it more simple:
function hello(status ) {
console.log('world', ++status.count);
return status;
}
setInterval(hello, 5 * 1000, hello({ count: 0 }));
If you can use RxJS, there is something called timer():
import { Subscription, timer } from 'rxjs';
const INITIAL_DELAY = 1;
const INTERVAL_DELAY = 10000;
const timerSubscription = timer(INITIAL_DELAY, INTERVAL_DELAY)
.subscribe(() => {
this.updateSomething();
});
// when destroying
timerSubscription.unsubscribe();
With ES2017, it may be preferable to avoid setInterval altogether.
The following solution has a much cleaner execution flow, prevents issues if the function takes longer than the desired time to complete, and allows for asynchronous operations.
const timeout = (delayMs) => new Promise((res, _rej) => setTimeout(res, delayMs));
const DELAY = 1_000;
(async () => {
while (true) {
let start_time = Date.now();
// insert code here...
let end_time = Date.now();
await timeout(DELAY - (end_time - start_time));
}
})();
There's a problem with immediate asynchronous call of your function, because standard setTimeout/setInterval has a minimal timeout about several milliseconds even if you directly set it to 0. It caused by a browser specific work.
An example of code with a REAL zero delay wich works in Chrome, Safari, Opera
function setZeroTimeout(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage('');
}
You can find more information here
And after the first manual call you can create an interval with your function.
actually the quickest is to do
interval = setInterval(myFunction(),45000)
this will call myfunction, and then will do it agaian every 45 seconds which is different than doing
interval = setInterval(myfunction, 45000)
which won't call it, but schedule it only