Javascript Promise Single Function Callback - javascript

I have two ways to run a series of initialisations (that need to happen in a particular order).
Method 1:
dispatch('initialize1')
.then(dispatch('initialize2'))
.then(dispatch('initialize3'))
.then(dispatch('initialize4'))
.catch((error) => Log(error.message))
Method 2:
dispatch('initialize1')
.then(() => dispatch('initialize2'))
.then(() => dispatch('initialize3'))
.then(() => dispatch('initialize4'))
.catch((error) => Log(error.message))
Method 2 works perfectly, but Method 1 seems to not wait for each to finish before it moves onto the next one.
But this really confuses me because I thought that if I chained promises with thens (no callback function), it would wait for each to complete (synchronously); but if I put each promise in a callback then as soon as it received the promise it'd move onto the next - but it's the opposite??
Can anyone explain this to me?
I don't think it's relevant, but the dispatch comes from Vue's Vuex Store.

In method 1, you passed the result of calling the function dispatch instead of passing a function to the Promise chain, this will cause the dispatch functions be called first before the Promise chain actually starts executing, i.e. the dispatch functions has already been called when you initialize the chain.
You can check it out directly by running the following code right at your browser's console:
const dispatch = something => something
typeof dispatch('apple') === 'string' // true
typeof (() => { dispatch('apple') }) === 'function' // true
In method 2, you are passing functions this time, so the functions will be called at the right time by Promise, instead of being run at start.

Because you need a wrapper function in the first case:
.then(function() {
dispatch('initialize2')
})
Here you do the same thing:
.then(() => dispatch('initialize2'))
() => ... is a wrapper function similat to function() {...}.

You should take a look at how promises are supposed to work. In short they are made of two pieces, a resolvealgorithm and a then method available on promise instances. Your first example cannot work because it does not follow the semantics ( signature ) of the then method.
They are as follow : let p a promise, f a JS value. Calling p.then(f) we have the following case :
if f is not a function it is ignored, and p.then(f) returns a new promise q eventually settled with the same state as p.
if f is a function then when p is settled with a value, calling p.then(f) will return a new promise q which will be settled with the value / error produced by f. This is the critical part and what makes promises interesting : the procedure you pass in to the then attr will only be called after a value / error has first been produced by the original promise, hence your issue with example 1.
There is ofc a little bit more than that to promises and their semantics : thentakes two arguments, one for each path : value / error. The namings may differ but usually you see code along the lines :
p.then(proceed, handle)
with
function proceed ( successfulValueFromSomewhere ) { // return new value or promise }
function handle ( anErrorFromSomewhere ) { // handle it by returning a value or a promise ( for retry cases ) }
I mentioned earlier a resolve algorithm, this part is critical to understand how values returned from such handlers are used from the point of view of promises to create new promise.
This procedure ensures that your second example work, it works more or less like that ( please take a look at the specs or the docs at MDN for an in depth review ). Its purpose is to transition a promise to one of two states : fulfilled with a value or rejected with an error.
Let v be a value, p an unsettled promise to be resolved with v.
if v has a then method then call it with the function function ( v2 ) { resolve(v2); } : which means that if the callback is called, rerun the procedure with the value provided (v2).
if v does not have a then method then fulfill with v
if at any point an error is thrown during the resolution then rejectwith the error.
This procedure is not really difficult and explains why promises compose nicely together : they will call each other's thenmethod upon resolution, which means that they will execute sequentially if each callback returns a promise.
There is a bit more than that to the specs of promises, I strongly advise anyone to take a look at the articles on MDN and this article about the motivations behind this new primitive added to the language and how it solves (some) problems.
If this answer is obscure please comment I'll try to be clearer :)

Related

Reusing an existing Promise object if exists

I have a Dialog object that will show, well, dialogs. There are many entry points to show dialogs, e.g. yesNo(), message(), confirm(), etc. However, all these methods basically call the same other method, called showSimpleDialog(title, message, buttons).
I'd like all these methods (showSimpleDialog too) to return a promise, but there's a snag:
yesNo() {
return new Promise((resolve, reject) => {
axios
.get(......)
.then(this.showSimpleDialog(...));
}
}
As you can see, I am prevented in the above example from either returning the promise that showSimpleDialog would make or by passing the instanced Promise to showSimpleDialog.
The former is impossible because we're already in a different Promise by the time we have access to it. The latter because the Promise object itself is not yet available within the constructor. Well, technically, in this particular case it is (exactly because we're already in a different Promise), but some of my entry functions are synchronous, some asynchronous and I simply can't use the same code pattern to achieve the same effect in both cases.
I investigated the thing and I found this, but the author suggests the approach is flawed and archaic to begin with.
So, what would be the correct approach to return a functioning Promise from ALL entry points while the entry points would still be free to reusing each other's Promises?
If I understand correctly, this.showSimpleDialog(...) also returns a Promise, right?
If you want yesNo() to return the Promise retunred by this.showSimpleDialog(...)
yesNo() {
return axios
.get(......)
.then(()=>{
return this.showSimpleDialog(...);
});
}
That being said, consider using async/await, especially when dealing with multiple sequential promises, if possible.
Your code is calling this.showSimpleDialog immediately (synchronously) without waiting for any promise to resolve (the axios one). This is because the code doesn't pass a function to the then method, but instead executes this.showSimpleDialog. This execution returns a promise (presumably), but then expects a function as argument, not a promise.
So you need to make sure to pass a callback to then, and let that callback return a promise. This way promises will be chained:
.then(() => this.showSimpleDialog(...));
It is also important to make that callback an arrow function, since you'll be referencing this, which is intended to be the this on which yesNo is called.

how handleSuccess gets the resolved value in js?

I have been going in circles trying to deeply understand JS promises and I can't seem to find a simple answer on how in the world does it passes the value of the resolved to the handle success variable, I don't understand is that as a build method? But the name is (resolvedValue)
For example, I saw also in another example that they used (rejectionReason) to handle the rejected value, I want to understand how that happens.
here is the code:
const prom = new Promise((resolve, reject) => {
resolve('Yay!');
});
// this resolvedValue how does it happen?
const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};
prom.then(handleSuccess); // Prints: 'Yay!'
First lets clarify on two different concepts:
Function Definition:
const exampleFunction=(name)=>{console.log(name)} // just defined, does nothing
Function Invocation:
exampleFunction("Erfan") // logs "Erfan"
In JavaScript, function definitions can be passed to another function ("a higher order function") as a parameter, usually we describe such situation as "the function taking a callback".
The higher order function then calls the callback according to its own implementation, and may or may not pass a value to it.
In your example, method then of the the prom is the higher order function. it takes a callback, passes the resolve value to it, and calls it. it doesn't care about its name, just looks for a function definition and calls it.
Credits to got to #Nirjal Paudel reference link, the answer to my question is :
it happens by paassing it in the value as an anonymous function.
Promises have a method called then that will run after a promise reaches resolve in the code. then will return the promise’s value as a parameter.
This is how you would return and log the value of the example promise:
const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};
prom.then(handleSuccess);
The promise you created had a [[PromiseValue]] of 'Yay!'. This value is what will be passed into the anonymous function as a response
so this means that the name won't matter

Race condition issues with async functions Javascript [duplicate]

I would like to get a deeper understanding of how Promises work internally.
Therefore I have some sample code:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Here a link to execute this code.
As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.
But the API ref states the following:
"then" returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Promise.resolve
So it would be interesting to know WHEN exactly the "then" function is executed?
Because the final "then" in the code is chained to the chainPromises(), I first thought that
it would execute after the function chainPromises() returns something (in this case another promise).
If this would have been the case the "val" of the final "then" function would be the returned promise.
But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved.
This absolutely makes sense because in this way, the "then" functions can be stacked, but
I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.
Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.
I hope I could make clear what I mean.. :)
About Promise resolution
The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:
onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
The ES6 promise specification (promises unwrapping) contains a similar clause.
This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.
In practice
This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.
This means the following:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
So for example:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
And that:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Is it a good idea?
It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.
In other languages
It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.
Let's start with an easy perspective: "chainPromises" returns a promise, so you could look at it this way:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Generally speaking, when returning a promise from within a "then" clause, the "then" function of the encapsulating promise will be marked as finished only after the internal "then" has finished.
So, if "a" is a promise, and "b" is a promise:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
So the output will be:
B!
Done!
Notice btw, that if you don't "return" the internal promise, this will not be the case:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Here we can't know what would be outputted first. It could be either "B!" or "Done!".
Please check the below example regarding how promises works:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1: shoe ticket');
console.log('person2: shoe ticket');
const promiseGirlFriendBringingTickets = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ticket');
}, 3000);
});
promiseGirlFriendBringingTickets.then((t) => {
console.log(`person3: show ${t}`);
})
console.log('person4: shoe ticket');
console.log('person5: shoe ticket');
Promise then return promise object, not promise's resolved value. I forked your JsFiddle, and added some of mine try this.
promise.then is executed right after that promise object is resolved.
I do not know how this is done in actual promises libraries, but I was able to re-create this functionality in the following way:
1) each promise has a waitingPromises property;
2) then method returns a new promise, and the original promise's waitingPromises property points to the new promise.
In this way, the chain of .then()s creates a structure that is similar to a linked list or rather a tree (each promise can have several waiting promises). A promise can be resolved only after its 'parent' promise has been resolved. The .then method itself is executed immediately, but the corresponding promise that it creates is resolved only later.
I am not sure this is a good explanation and would love to learn about other possible approaches.
Normally code is synchronous - one statement executes like (fileopen) and there is a guarantee that the next statement will execute immediately afterwards like filewrite()
but in asynchronous operations like nodejs, you should assume that
you have no idea when the operation will complete.
You can't even assume that just because you send out one request first, and another request second, that they will return in that order
Callbacks are the standard way of handling asynchrnous code in JavaScript
but promises are the best way to handle asynchronous code.
This is because callbacks make error handling difficult, and lead to ugly nested code.
which user and programmer not readble easily so promises is the way
You can think of Promise as a wrapper on some background task. It takes in a function which needs to be executed in the background.
The most appropriate place to use a promise is where some code is dependent on some background processing and it needs to know the status of the background task which was executed. For that, the background task itself accepts two callback resolve and reject in order to convey its status to the code which is dependent on it. In layman terms, this code is the one behind it in the promise chain.
When a background task invokes resolve callback with some parameter. it's marking the background operation successful and passing the result of the background operation to the next then block which will be executed next. and if it calls reject, marking it as unsuccessful then the first catch block will be executed.
In your custom promise, you can pass an error obj to the reject callback so that next catch block is aware of the error happened in the background task.

Why promise chains can be flattened?

The following code contains two kinds of promise chain, seems they'r equivalent, but I don't understand why they are equivalent. I think of it like 2*(3+4) = 2*3+4, which is not correct.
// example1
runAsync1()
.then(function(data1){
return runAsync2()
.then(function(data2){
return runAsync3();
})
})
.then(function(data3){
console.log(data3);
});
// example 2
runAsync1()
.then(function(data1){
return runAsync2();
}).then(function(data2){
return runAsync3();
}).then(function(data3){
console.log(data3);
});
Maybe some braces would help you understand this a little better. (NOTE: this is exactly the same thing as you had except with an extra set of braces on the return)
// example1
runAsync1()
.then(function(data1){
return (
runAsync2()
.then(function(data2){
return runAsync3();
})
)
})
.then(function(data3){
console.log(data3);
});
So what is happening here,
.then is called on runAsynch1()
.then is then called on runAsynch2() which returns runAsynch3() (this return carries on all the way down the chain of returns)
finally .then is called on the returned runAsynch3()
As you can see, this is exactly the same process as what happens in example 2
// example 2
runAsync1()
.then(function(data1){
return runAsync2();
}).then(function(data2){
return runAsync3();
}).then(function(data3){
console.log(data3);
});
It's a little bit implementation-specific, but the magic, regardless of the specifics is in the then.
Then does a couple of things.
The TL;DR is that then subscribes to returned promise chains, but below are examples closer to the guts of a promise.
The first thing is:
"Is the promise still pending? Then schedule these callbacks for later; otherwise, schedule this callback to run on the next tick (setTimeout(handle, 0)). Return a new promise that resolves/rejects to the eventual value."
// basically accurate-ish
then (onSuccess, onError) {
return new Promise((resolveNext, rejectNext) => {
if (myPromiseIsDone) {
// I already have the value; run the next step ASAP
// this is ugly, but hopefully it proves a point
runOnNextTick(onSuccess, onError, promiseResult, resolveNext, rejectNext);
} else {
// I don't have a result yet; come back when it's ready
scheduleWhenDone(onSuccess, onError, resolveNext, rejectNext);
}
});
}
The second is where your answer lies:
"Run the handler. Get the return value from the callback passed to then. Is the return value a Thenable object (has a then method)? Then call then and pass in the resolve/reject functions that control my promise... otherwise, resolve/reject accordingly, based on whether it throws or returns."
// entirely subjective and implementation-specific,
// but the algorithm is almost spec-compliant
handleSuccess (onSuccess, resolveNext, rejectNext, value) {
if (!onSuccess) {
// if they didn't give me a `then(callback)`,
// just pass the value to the next promise
resolveNext(value);
return;
}
try {
// I'm running the `then(callback)` here
const result = onSuccess(value);
if (hasThenMethod(result)) {
// it's promise-like, subscribe
result.then(resolveNext, rejectNext);
} else {
resolveNext(result);
}
} catch (err) {
// something blew up, while trying to succeed, so fail
rejectNext(err);
}
}
Reject looks similar.
So the outer then subscribes to the inner then.
If you ever wanted to get into functional programming, the ES6 Promise is almost a monad.
The difference is that a monad would force you to have a different method, to tell it to chain to the returned promise, rather than doing it automatically.
then is basically the same as map on arrays. You call then, pass it a function that gets the value and returns a new promise with the transformed value.
So a monadic promise might be one that has map and chain, or then and chain, where chain does almost exactly the same thing but says "hey, then, this callback is going to return a promise; subscribe to that one, so that you flatten it out, rather than returning a promise of a promise of a value".
That's almost all it would take to be a monad.
Hope that all helps.

multiple functions inside of angular then()

Sometimes I see more than two functions separated by comma, inside of promise then() in AngularJs. Could anyone here help to explain what the structure mean?
e.g.
then(function(response){..}, function(response){..}, function(response){..}, function(response){..});
I understand that, if there are two functions inside of then(). The first function will run if it fulfill the promise, otherwise the second will run if there is any error occurs. This structure doesn't look like chained promise either...
Thank you very much for any help here :-)
Well:
The first function is the fulfillment handler, it will execute when the promise resolves to a value (normally).
The second function is the rejection handler, it will execute when the promise resolves with an error by rejecting (or throwing an exception in a handler).
The third function is for progress, this is a nonstandard and deprecated feature that will never be a part of ECMAScript promises - it is best to avoid it altogether since it does not compose well. It is also not supported in Angular's new $q API.
Anything past the third function passed in is ignored by the handler and will have no effect.
Here is an example for all three being called:
var good = $q.when(3);
good.then(x => console.log("Successful"));
var bad = $q.reject(Error("Bad")); // always reject with errors
bad.then(null, x => console.log("Failed"));
var d = $q.defer(); // don't do this like... ever
d.promise.then(null, null, x => console.log("Progressed"));
d.notify("event notification"); // never use this in real code ;)

Categories

Resources