I have 4-5 JavaScript functions which calls ajax and respond after sometime, but for example I am giving example of 3 functions without ajax code.
Here I want to ensure that func3 will call after two other functions func1 and func2.
func3();
func1();
func2();
function func1(){
setTimeout(function(){
console.log("func1");
}, 2000);
}
function func2(){
setTimeout(function(){
console.log("func2");
}, 3000);
}
function func3(){
setTimeout(function(){
console.log("func3");
}, 1000);
}
I want total time would be 4 seconds. func1 and func2 would run simultaneously in 3 seconds and then func3 in 1 second.
Call them at the end of the func before?
func3();
function func1(){
console.log("func1");
func2();
}
function func2(){
console.log("func2");
}
function func3(){
console.log("func3");
func1();
}
Edit 1:
func1();
function func1(){
setTimeout(function(){
console.log("func1");
func2();
}, 1500);
}
function func2(){
setTimeout(function(){
console.log("func2");
func3();
}, 1500);
}
function func3(){
setTimeout(function(){
console.log("func3");
}, 1000);
}
Just a quick primer on Promises:
A promise is an object that basically says, "This work isn't done yet, but I'll let you know when it is."
When you create a Promise, you can attach callback functions using .then(). When the promise is resolved - that is to say, it's work is finished - all of the callbacks will be executed. You can also attach callbacks with .fail() or something similar, and these will be executed if the Promise is rejected.
In your case, you might do something like:
func1().then(func2).then(func3);
function func1(){
var p = new Promise();
setTimeout(function(){
console.log("func1");
p.resolve();
}, 2000);
return p;
}
function func2(){
var p = new Promise();
setTimeout(function(){
console.log("func2");
p.resolve();
}, 3000);
return p;
}
function func3(){
var p = new Promise();
setTimeout(function(){
console.log("func3");
p.resolve();
}, 1000);
return p;
}
In addition, most Promise Libraries have a .whenAll() type function. This takes multiple Promises and calls its .then() callbacks when all promises have completed. So you could do:
whenAll(func1(), func2()).then(func3);
If you are in an environment where you can use EcmaScript6, there is a built in Promise library. Read this MDN article for information on that library.
Otherwise, I strongly recommend jQuery's promise library.
Note: The above code is just psuedocode. Read the documentation to see how to actually implement the Promises in those frameworks.
I made it as I want, like this. But I don't know its good of bad practice, I am not aware of promise and get some answer's but those were not working.
start = 0;
func1();
func2();
function func1(){
setTimeout(function(){
console.log("func1");
start++;
if(start==2){
func3();
}
}, 2000);
}
function func2(){
setTimeout(function(){
console.log("func2");
start++;
if(start==2){
func3();
}
}, 3000);
}
function func3(){
setTimeout(function(){
console.log("func3");
}, 1000);
}
Note : first function func1 prints in 2 seconds func2 in 1 second because 2 already gone, and then func3 in 1 second total 4 seconds cheers :)
let promises = [];
let ajaxCall = new Promise((resolve, reject) => {
console.log('ajaxCall');
setTimeout(() => {
resolve();
},1000);
});
let fn1 = new Promise((resolve, reject) => {
console.log('fn1');
ajaxCall.then(() => {
resolve();
});
});
let fn2 = new Promise((resolve, reject) => {
console.log('fn2');
ajaxCall.then(() => {
resolve();
});
});
promises.push(fn1);
promises.push(fn2);
Promise.all((promises)).then(() => {
console.log('fn3');
});
Hope this helps
Related
I know 2 will be console.logged first and then 1. Is there any way, maybe with callbacks, I can show 1 first and then 2?
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
Put second()'s call in the setTimeout:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
second();
}, 500 );
}
function second(){
console.log(2);
}
first();
You could also bypass first, second and setTimeout completely:
console.log(1);
console.log(2);
function second(){
console.log(2);
}
function first(cb){
// Simulate a code delay
return setTimeout( function(){
console.log(1);
cb();
}, 500 );
}
first(second);
Solve it by promise a clan and elegant way:
function second() {
console.log("test2", 2);
}
function first() {
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("test1", 1);
resolve();
}, 500);
});
return promise;
}
first().then(function () {
second();
});
don't use timeout call in first function. or you can use promises
for better understanding of event loop callback execution order read this article
link. this article explains execution order , which get priority among promise , timeout etc
Hope it will help
I was following this tutorial and it was all making perfect sense until...
function first(){console.log('first')}
function second(){console.log('second')}
first()
second()
//first
//second
then:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
//2
//1
I get all that, but I don't understand how to then implement a callback so that it logs:
//1
//2
in that order.
I know it will be something like:
function first(cb){
// Simulate a code delay
setTimeout( function(){
console.log(1);
cb()
}, 500 );
}
but this blows up. can someone help me see how to use the callback correctly
It should be:
function first(cb){
setTimeout( function(){
console.log(1);
cb(); // <-- calling 'cb' is calling 'second'
}, 500 );
}
function second() {
console.log(2);
}
first(second); // pass 'second' as value of cb
UPDATE:
In case you want to use promises (as you mentionned in your comment), it should be:
function first() {
return new Promise(function(resolve) { // <-- Make the first function returning a promise.
setTimeout(function() {
console.log(1);
resolve();
}, 500);
});
}
function second() {
console.log(2);
}
first().then(function() { // <- 'first' returns a promise so you can .then on it
second();
});
I have 3 functions, assume they are function a, b and c. All of them require a delay to start in different scope.
I can do in different places and event like this
setTimeout(function()a()},100);
setTimeout(function()b()},100);
setTimeout(function()c()},100);
but how can I make it cleaner?
This is exactly what ES6 Promises were made for.
function a() { console.log('a') }
function b() { console.log('b') }
function c() { console.log('c') }
function foo() {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve();
}, 100);
});
}
foo()
.then(a)
.then(b)
.then(c)
I understand this example is a little vague. But if you understand promises you can adapt it pretty well to your problem (and if you are not familiar with promises you can master Promises in a matter of hours).
You could also use Observables from Rjrx. The "fromInterval" operator is what you are looking for. Observables might be part of ES7.
You can try this approach.
function a() {
console.log("function a");
}
function b() {
console.log("function b");
}
function c() {
console.log("function c");
}
function callFunction(ref) {
setTimeout(function(){
ref();
},5000);
}
callFunction(a);
callFunction(b);
callFunction(c);
/* These are anonymous function. These will never wait for each other ro execute.*/
setTimeout(function(){a();},5000);
setTimeout(function(){b();},5000);
setTimeout(function(){c();},5000);
Before we start, as its common misconception, you must know that setTimeout time passed doesn't mean it will be executed exactly after 100ms. It can be longer (just not earlier). You should definitly watch a great talk by Philip Roberts - What the heck is the event loop anyway?.
Edit - as my answer covers setTimeout-way I think the answer given by #Adam Kettani is what you need, as with promises you can be sure the code will be executed in the right time and order, and it is also more clean what is going on.
Okay, let's get down to business. You can put them in array and then use a `forEach
const functions = [
function (){
console.log('a');
},
function (){
console.log('b');
},
function (){
console.log('c');
},
];
functions.forEach(fn => setTimeout(fn, 1000));
Keep in mind that they all will be set with timeout 1000ms, so they will most likely execute at the same time. If you want to have a delay in-between too just modify forEach:
const functions = [
function (){
console.log('a');
},
function (){
console.log('b');
},
function (){
console.log('c');
},
];
functions.forEach((fn, index) => setTimeout(fn, index * 2000));
To make this generic you can extract this line of code to a function:
const functions = [
function (){
console.log('a');
},
function (){
console.log('b');
},
function (){
console.log('c');
},
];
function _setTimeout (fn, delay) {
// setTimeout returns a value that allows you to
// cancel timeout, so it would be great if our function
// has this feature of converting array of functions
// to array of timeout ids
return fn.reduce((timeoutIds, fn, index) => {
return [...timeoutIds, setTimeout(fn, index * delay)];
}, []);
}
const timeouts = _setTimeout(functions, 2000);
console.log(timeouts);
clearTimeout(timeouts[2]);
console.log('C shall not pass!');
I need to execute 2 functions one after the other with the stuff in function "A" fully completing before the stuff in function "B" executes...
I can't find an example that is not using setTimeout .. which is strange ...
I have the following example below ( from here ) , is it supposed to work ?? How could I test if it is working ? What dummy code could I use to simulate the part "//do stuff with SharePoint JSOM" taking 5 secs to 30 secs ,say .
var a = function() {
var defer = $.Deferred();
//do stuff with SharePoint JSOM
console.log('a() called');
return defer;
};
var b = function() {
var defer = $.Deferred();
console.log('b() called');
return defer;
};
a().then(b);
Simple use a promise (vanilla JS) and chain them with then.
function a() {
return new Promise(function(resolve) {
console.log("wait two seconds ...");
// this timeout is only here for demo purpose ;)
setTimeout(function() {
console.log("A");
resolve();
}, 2000);
});
}
function b() {
console.log("B");
}
a().then(b);
If you want to use jQuery deffered its nearly the same.
function a() {
var defer = $.Deferred();
console.log("wait two seconds ...");
// this timeout is only here for demo purpose ;)
setTimeout(function() {
console.log("A");
defer.resolve();
}, 2000);
return defer;
}
function b() {
console.log("B");
}
a().then(b);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm creating a game where user writes a function that will execute and do stuff such as move a robot/rotate etc.
I've got this code :
function move(){
setTimeout(function(){
console.log("Log 1,5");
}, 3000);
return true;
}
function anotherMove(){
setTimeout(function(){
console.log("Log 2,5");
}, 2000);
return true;
}
function action(){
console.log("Log 1");
move();
console.log("Log 2");
anotherMove();
console.log("Log 3");
}
action();
Imagine move/anotherMove as robot movement and console.logs as calculations between those moves. Is there anyway to output logs correctly : 1 -> 1,5 -> 2 -> 2,5 (currently its 1 -> 2 -> 3 -> 1,5 -> 2,5) so basically that console.log waits for move/anotherMove to complete before executing these logs.
I can change move/anotherMove structure (it will be canvas animation) but I need action() structure stay as it is...
Thanks a lot !
Promises do just what you're looking for. These are available in ES6, or there are several libraries, for example, Q.
You'll start wrapping timeout in a promise...
function timeout(ms) {
return new Promise(function (resolve, reject) {
setTimeout(resolve, ms);
});
}
Now that timeout function will return a promise, which can be chained with another promise using the function then(). So, for example, your move() function can be improved as ...
function move(aString, aDelay) {
return timeout(aDelay).then( () => {
console.log(aString);
true;
});
}
The action function almost writes itself...
function action() {
console.log("Log 1");
return move("Log 1.5", 3000).then(() => {
console.log("Log 2");
move("Log 2.5", 2000);
}).then(() => {
console.log("Log 3");
});
}