Jquery - Chain functions with deferred and promises but without setTimeout - javascript

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>

Related

javascript callback - execution of scripts is in random order

I have this problem - while executing this function
function(){
var after = function(){
server.executescript("scriptname")
};
var before = function (callback) {
server.executescript("scriptname2")
callback();
};
before(after);
}
execution of scripts is in random order and not as I would expect:
scriptname2
scriptname
what am I missing?
Thank you!
this seems to work
function(){
function after(){
server.executescript("scriptname");
}
function before(){
return new Promise((resolve, reject)=>{
server.executescript("scriptname2");
resolve();
});
}
before().then(after);
}
thank you all for participating!
The order you are seeing is the one expected:
var after = async function() {
await console.log("scriptname");
};
var before = async function (callback) {
await console.log("scriptname2");
callback();
};
before(after);
You first call the "before()" function which is going to call your "scriptname2".
Then you will call your "callback()" which is your "after()" function.
Which is going to call your "scriptname".

How to ensure to call function after all other functions

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

Using deferred to chain loops with multiple ajax calls

There are multiple questions that already have an answer about this, but all aren't working so far it this kind of setup.
function login(u,p) {
console.log(1);
return $.post(url, {u,p});
}
function out() {
console.log(3);
//a function that does not return deferred
// clear cookies
}
function doSomething() {
console.log(2);
// a function that returns a deferred
return $.post(...);
}
var data = [{u: 'au', p: 'ap'}, {u: 'bu', p: 'bp'}]
$.each(data, function(k,v){
login(v.u, v.p).then(doSomething).then(out);
});
I was expecting it's sequence to be like:
1
2
3
1
2
3
But I get
1
2
1
3
2
3
Why is it like that, even though I am waiting for the promise to be resolve using then
If you want the logins to run synchronously:
var p = new jQuery.Deferred();
$.each(data, function(k,v){
p.then(function() {
return login(v.u, v.p);
}).then(doSomething).then(out);
});
Each new item iterated over in $.each won't trigger a new response until p finishes the last one.
The idea is to create a recursive function like #Popnoodles have mentioned.
e.g.
function a() {
return $.post();
}
function b() {
return $.post();
}
function c() {
console.log('no promise.');
}
// and the recursive main function
function main() {
if(counter < data.length){
$.when(a().then(b).then(c)).done(function(){
counter++;
main();
});
}
}
main();
Here is how it works, open the console to see how it logs the function in sequence.

Understanding promises in javascript using when library

I've been trying to wrap my head around asynchronous programming and the use of promises. To help understand them, I've written some trivial nested code, but have run into a snag.
Here's the code: http://pastebin.com/hBtk9vER
Make sure you install when library (npm install)
var when = require('when');
function promise() {
console.log("Promise");
promiseRead().then(function(string) {
console.log("Inner promise");
console.log(string);
});
}
function promiseRead() {
console.log("PromiseRead");
return baz().then(function() {
console.log("Inner Read");
var deferred = when.defer();
setTimeout(function() {
deferred.resolve("Hello World");
}, 5000);
});
}
function baz() {
console.log("BAZ");
return when(true);
}
promise();
My problem is that console.log(string) is undefined, when I was expecting it to be "Hello World" after promiseRead() resolves. Interestingly, when I remove the timeout, it works as expected. Can anybody help explain this, why the promise function is executing it's code before promiseRead() has finished timeout.
Much appreciated
It looks like you need to return your deferred object in promiseRead()
some updates
var when = require('when');
function promise() {
console.log("Promise");
promiseRead().then(function(string) {
console.log("Inner promise");
console.log(string);
});
}
function promiseRead() {
console.log("PromiseRead");
return baz().then(function() {
console.log("Inner Read");
var deferred = when.defer();
setTimeout(function() {
deferred.resolve("Hello World");
}, 5000);
return deferred.promise;
});
}
function baz() {
console.log("BAZ");
return when(true);
}
promise();

Tell when multiple onLoad events have been completed in javascript

I have to load two apis. The YouTube api which calls onYouTubePlayerReady when it has loaded and another api for SoundManager which calls soundManager.onready(...) when it has loaded. I do a lot of stuff in each of these ready functions to prepare the site. However, I also need to know when both have completed so I can do more initialization that require both to be fully loaded. Any idea how to have a function that is called when both of these ready functions are called?
Use a callback for both of them.
var callback = (function(){
var count = 0;
return function(){
count++;
if(count === 2){
//both ran and do something
}
}
})();
Then in the end of both onloads just do:
callback();
The things in that if statement will only run on the second time this function i s called.
Small fiddle demo: http://jsfiddle.net/maniator/2X8rF/
Just set a couple flags:
var aDone = false;
var bDone = false;
function whenADone(){
// do your other stuff
aDone = true;
if(bDone) whenBothDone();
}
function whenBDone(){
// do your other stuff
bDone = true;
if(aDone) whenBothDone();
}
There is probably a better way with Defered's, but this is simple and should work. Just keep track of what loaded and what didn't.
var status = {
youtube: false,
sound: false
};
var loaded = function() {
if (!status.youtube) return;
if (!status.sound) return;
// load stuff!
};
var onYoutubePlayerReady = function() {
status.youtube = true;
loaded();
};
soundManager.onready = function() {
status.sound = true;
loaded();
}
Using jQuery deferred, you could build promises for each ready function and combine them with jQuery.when to trigger a final action. For example
function promiseYoutube() {
var dfd = $.Deferred();
window.onYoutubePlayerReady = function() {
console.log("Youtube");
dfd.resolve();
};
return dfd.promise();
}
function promiseSoundManager() {
var dfd = $.Deferred();
window.soundManager.onready = function() {
console.log("SoundManager");
dfd.resolve();
};
return dfd.promise();
}
$.when( promiseYoutube(), promiseSoundManager() ).then(function(){
console.log('Youtube+SoundManager');
});
And a Fiddle simulating these callbacks http://jsfiddle.net/nikoshr/hCznB/
You could have both of your readys set a boolean to true then test against those a $(document).ready(function () { if (youTube === true && soundManager === true) { // Do stuff }});
If using jQuery, take a look at deferred:
http://www.erichynds.com/jquery/using-deferreds-in-jquery/
http://api.jquery.com/category/deferred-object/
Thanks

Categories

Resources