When using promises why is the last then called? - javascript

I'm watching this video(code around 36 minutes) on Promises, but I'm confused by a bit of code:
getUser('mjackson')
.then(getTweets)
.then(updateStatus)
.then(undefined, handleError);
My problem with understand this is why is the last then called? And why does it pass undefined as the first argument?
If getTweets() fails, then updateStatus() is never called. Which is why I'm confused as to why the last then is called if the second (the one that contains updateStatus()) isn't.
I know handleError is a callback, I just don't get why undefined is passed.
I hope that makes sense.

Any then with a function provided as the second parameter will catch and handle any rejected promises farther up the promise chain.
So if getUser or getTweets or updateStatus fails, the error will be handled in handleError.
This code is passing undefined as the first parameter because in this case updateStatus is the last thing that the person writing it wants to do, and there's nothing more to do if that succeeds.
Most promise libraries, and the ES6 promise standard provide a .catch(...) method that is really just a shorthand for .then(undefined, ...):
getUser('mjackson')
.then(getTweets)
.then(updateStatus)
.catch(handleError);

There are two ways of using the promise methods, for async flow control, particularly for error-handling.
The first is:
anOperation.then(onsuccess, onerror);
The second is:
anOperation.catch(onerror);
If onsuccess is undefined or null in the first case, it means that there is no success option there (so it would move to the success after that one, in the success case).
Most promises you see/use are .then(onsuccess, undefined).
It should be noted:
If you throw an error in onsuccess, the onerror does not get fired. It moves to the next error down. It is impossible to fire both callbacks in the same .then, it's an either-or scenario
If you return a value from a .catch or an onerror callback, it is expected that you have solved the issue, and thus, you go into the next onsuccess of the next .then, with the value you returned. If this isn't what you want, rethrow, or return a Promise.reject

The signature of the then function is:
p.then(onFulfilled, onRejected);
If you pass undefined as the first parameter, it behaves as p.catch(onRejected);
In a then chain, every success functions will be called in an order unless one failed. If one failed, all the execution will break unless a second parameter of a then exists. The second parameter will behave the catch of any.
If a then function returns a promises, you can make a then chain.
handleError has called, because one of the previous promises in the chain was failed.
Promises in a chain with an example
Here my JsBin to understand a promise chain. Try to change giveMeSuccessPromise and giveMeFailPromise functions in doX or catchX functions.
In a chain of then clauses as below:
p.then(doFirst)
.then(doSecond)
.then(doThird)
.then(undefined, catchFirstSecondThird)
.then(doFourth)
.then(doFifth, catchEveryThing);
In this example, in case of any of the doFirst, doSecond or doThird failed catchFirstSecondThird will be executed. In case of any of the catchFirstSecondThird, doFourth or doFifth failed catchEveryThing will be executed.
The order of the execution in happy path:
doFirst, doSecond, doThird, doFourth, doFifth
The order of the execution when only doFirst fails:
doFirst, catchFirstSecondThird, doFourth, doFifth
The order of the execution when only doSecond fails:
doFirst, doSecond, catchFirstSecondThird, doFourth, doFifth
The order of the execution when both doFirst and doFourth fails:
doFirst, catchFirstSecondThird, doFourth, catchEveryThing
Resources:
From MDN, Promise API
From MDN, API of then
From MDN, API of catch
A very good tutorial about promises

Related

Does the then() function return a promise reflecting the results of the previous promise?

I am new to promises and have studied it. So my code and my understanding:
sql.connect(config).then(function(connection) {
return connection.request().query('select * from Users')
}).then(function(result) {
console.dir(result);
res.send(result);
}).catch((err) => {
console.log(err);
res.send(err)
});
}) // extra?
In the first line, the connect method returns a promise so on that, when I call a function then (if connect had success). The then takes callbacks i.e. "successCB", "failureCB" as arguments which actually represent the result or error returned by the connect promise. Correct?
Also, the "successCB" is returning the promise (from .query).
then is again called on the previous promise returned by then.
In case of then used on connect() why is the then taking a callback and how does it know of connect's success since connect has already returned the result i.e. "successCB"?
I'm not 100% certain if you are correct, but this is how I would explain it. Lets say we have a promise A.
Calling then() always returns a new promise (Lets call it B)
If the callback returns a promise C, then promise B will resolve or fail with the result of promise C.
If any of the callbacks returns a non-promise value X, then promise B will resolve with value X
If an exception was thrown in the callback, then promise B will fail with the exception.
If the main promise A failed, and no failure callback was given, then promise B will also fail with the same error.
Personally I found learning this very confusing, because it requires quite a complex mental model to fully grasp this. The day I fully understood this is the day that I wrote my own Promise class. I would recommend anyone who fully wants to grasp promises in every detail to take the time to do this.
In the first line, the connect method returns a promise so on that, I call a function then (if connect had success).
Almost: the then method is called irrespective of the connect promise's result. Note that the promise is most likely still pending when the then method is called. It is called (obviously) synchronously.
The then takes callbacks i.e. successCB, failureCB as an args which actually represents the result or error returned by the connect promise. Correct?
Those callbacks are registered by the promise object, and one of them will be called later when the promise resolves: it can either fulfil or reject. If the promise never resolves, neither will be called. In your case, you provided just one function, the one that will be called when the promise fulfils.
Also, the successCB is returning the promise (from .query).
True. The promise that was created when the outer then was executed will take over the status/value of the promise that was returned here.
then is again called on the previous promise returned by then.
Yes, but again, it is called immediately. All chained then/catch methods are called synchronously and their job is to register the callbacks and to return a promise.
The asynchronous part is when the respective callbacks are called. This is when the cascading effect takes place. Once the first promise (query()) in the chain resolves, the respective callback is called and that call resolves (fulfils or rejects) the promise that was already returned by then, which triggers a next callback... etc
Order of execution
Part A
sql.connect(config)
calls connect and returns a promise
.then(......)
calls then on the promise of A.1, registers the callback and returns a promise
.catch(.....)
calls catch on the promise of A.2, registers the callback and returns a promise.
This happens to be the last one in the chain, so this promise is the value of the whole expression.
At this point the synchronous part ends. If there is other calling code on the callstack, it gets executed, but eventually the call stack will be empty.
Part B
Then, some time later, there is an event indicating that the promise of A.1 is resolved, let's assume it fulfils (i.e. success). Then the first callback is executed:
connection.request() is executed
it calls request which returns an object with the query method (among others)
.query('select * from Users') is executed
it calls query with the SQL and returns a promise
return is executed
the callback returns the promise of B.2, which becomes linked with the promise that was created in step A.1.
At this point the promise of step A.1, is still pending. Its destiny is tied up now with the promise that was returned by query, B.2. It that one resolves, A.1 will also resolve (with the same state & value/error).
Part C
Then, some time later, there is an event indicating that the promise of step A.1 is resolved, let's assume it fulfils. Then the second callback is executed:
console.dir(result) is executed
res.send(result) is executed
Nothing is returned, so the promise of 1.B fulfils with value undefined
This fulfilment creates a next asynchronous job to execute (part D)
Part D
The promise returned by catch (A.3) resolves with the value with which C.3 resolved, i.e. it fulfils with value undefined. The callback it had registered is not executed, as it is not relevant for this scenario.
Thanks for replies and I have already selected the answer. Based on the input given by you people this is what I have understood further.
sql.connect(config).then(function(connection) {
return connection.request().query('select * from Users')
})
In the code given above, sql.connect part is using an SQL module to call a connect() method which is supposed to return a promise (in case of failure returns an error else a connection object). On connect() we call a then() method which takes a callback function function(connection) to get registered so that can be called later at the point where connect returns a promise (in case of success i.e. connection object) and later
.then(function(result) {
console.dir(result);
res.send(result);
}).
is called on the promise returned by .query('select * from Users') part of the previous .then() method's callback function and so on.

Can jquery promises be garbage collected before they resolve?

Consider the following:
function listFoo() {
return $.ajax(...);
}
function listFooey() {
return $.ajax(...);
}
function parallelLoad() {
//Note that we do *not* return the promise here.
$.when(
listFoo(), listFooey()
)
.then (function(fooResponse, fooeyResponse) {
console.log('then')
//doStuff
});
}
//Kick everything off and log
console.log('before parallelLoad');
parallelLoad();
console.log('after parallelLoad');
A typical output on the console would be (jsfiddle) :
before parallelLoad
after parallelLoad
then
The first two functions return the ajax Promise, so the reference to it is not lost. However, the parallelLoad() function does not return the promise, so when it is executed, it creates the promise, returns immediately, and the promise would appear to immediately go out of scope.
In practice, I have not seen a problem arise from this pattern, but I'm wondering if that's just "luck".
In the example above, is parallelLoad() "safe" in that (assuming the ajax calls run without server/network errors) the then clause will always execute?
Or is there a race condition where sometimes the ajax calls might not even be initiated or the promises might be garbage collected before the then clause can run?
(Currently I am using jQuery 3.3.1)
In general, promises that are not going to be resolved and are not longer needed can be garbage-collected before they are resolved.
This is not the case in your example however. Even while there is no obvious global variable holding onto the promise, it still is referenced from the running ajax requests. The requests created by listFoo() and listFooey() keep the callbacks installed on them alive, as they need to run them when they finish. In turn, these callbacks reference the promises (or at least, the deferred parts of them) and the callbacks installed on them, as they need to resolve the promises and call the callbacks when they run. In turn, these callbacks reference the promise (or deferred) created by the $.when call and the callback installed on it, as they still are needed until everything is settled. Only once both requests are done and all callbacks are executed, everything will be garbage-collected.
No, it can never happen that a promise will miss to invoke your callbacks because something got garbage-collected at the wrong time.
There's no problem there, the then will always execute.
One main obvious downside with this is since the parallelLoad promise is lost, there is no continuation and you cannot chain any other events to the success or failure of listFoo, listFooey.
I think the promise chaining style may be the cause of the confusion.
Look at it this way, if you rewrite parallelLoad like so (breaking the chain),
function parallelLoad() {
//Note that we do *not* return the promise here.
var whenPromise = $.when(listFoo(), listFooey());
whenPromise.then(function(fooResponse, fooeyResponse) {
console.log('then');
//doStuff
});
}
You can now probably easily see that the then part is simply just another line of code(with a callback) waiting to be called and so will not be garbage collected until it is done.
After the then gets called, parallelLoad will go out of scope for you, but the references to the promises and callbacks created therein are still held internally in memory until the promises are resolved/rejected and callbacks are called.
Nathan, Closures are about identifiers right? So parallelLoad() references both listFoo and listFooeyidentifiers (as functions) creating two closures. Those closures will remain in place until (at least) each of those functions complete and resolve. That means that parallelLoad() is the Execution Context and has not completed yet. The next step in the process is the .then() in response to the resolve.
That means the Execution Context (parallelLoad()) is established at the parallelLoad() call and does not change until all the code in the .then() has completed, it is a safe paradigm.

Why does the Promise constructor require a function that calls 'resolve' when complete, but 'then' does not - it returns a value instead?

As I plunge into studying Promises, my understanding has halted on the following question that I do not find discussed (all I find are specific discussions of the Promise constructor, and the Promise 'then' function - but not a discussion that compares their design patterns).
1. The Promise constructor
From the MDN documentation, we have this use of the Promise constructor (with my comment added):
new Promise(function(resolve, reject) { ... }); // <-- Call this Stage 1
Function object with two arguments resolve and reject. The first
argument fulfills the promise, the second argument rejects it. We can
call these functions, once our operation is completed.
2. The then function
Moving on to the then function that can be called on a Promise object (which returns a new Promise object), we have the following function signature as described by the documentation (with my comments added):
p.then(onFulfilled, onRejected);
Chaining
Because the then method returns a Promise, you can easily chain then
calls.
var p2 = new Promise(function(resolve, reject) {
resolve(1); // <-- Stage 1 again
});
p2.then(function(value) {
console.log(value); // 1
return value + 1; // <-- Call this Stage 2
}).then(function(value) {
console.log(value); // 2
});
My question
From the above code snippet, it seems clear to me that the value passed to the resolve function in Stage 1 (in the second occurrence of resolve - beneath (2), above) is passed on to the next stage (the first then function that follows in the same code snippet). There is no return value at Stage 1. However, it is the return value at Stage 2 that is passed on to the next stage after that (the second then function).
Is this lack of correspondence between the design pattern for the creation of a Promise, and the use of the then function on an existing promise (which also returns a Promise), just a historical fluke (one requires calling a callback but returns nothing, and the other returns a value but does not call a callback)?
Or am I missing an underlying reason why the Promise constructor utilizes a different design pattern than the then function?
Bergi's answer is excellent, and has been very helpful to me. This answer is complementary to his. In order to visualize the relationship between the Promise() constructor and the then() method, I created this diagram. I hope it helps somebody... maybe even me, a few months months from now.
The main idea here is that the "executor" function passed to the Promise() constructor sets tasks in motion that will set the state of the promise; whereas the handlers you pass to then() will react to the state of the promise.
(Code examples adapted from Jake Archibald's classic tutorial.)
This is a highly simplified view of how things work, leaving out many important details. But I think if one can keep a grip on a good overview of the intended purpose, it will help avoid confusion when one gets into the details.
A couple of selected details
The executor is called immediately
One important detail is that the executor function passed to the Promise() constructor is called immediately (before the constructor returns the promise); whereas the handler functions passed to the then() method will not be called till later (if ever).
Bergi mentioned this, but I wanted to restate it without using the terms a/synchronously, which can be confused if you're not reading carefully: The distinction between a function calling something asynchronously vs. being called asynchronously is easy to gloss over in communication.
resolve() is not onFulfill()
One more detail I'd like to emphasize, because it confused me for a while, is that the resolve() and reject() callbacks passed to the Promise() constructor's executor function are not the callbacks later passed to the then() method. This seems obvious in retrospect, but the apparent connection had me spinning in circles for too long. There is definitely a connection, but it's a loose, dynamic one.
Instead, the resolve() and reject() callbacks are functions supplied by the "system", and are passed to the executor function by the Promise constructor when you create a promise. When the resolve() function is called, system code is executed that potentially changes the state of the promise and eventually leads to an onFulfilled() callback being called asynchronously. Don't think of calling resolve() as being a tight wrapper for calling onFulfill()!
There is no correspondence between the Promise constructor and the then method because they are two independent things, designed for different purposes.
The Promise constructor is only used for promisifying1 asynchronous functions. Indeed, as you say, it is built on invoking resolve/reject callbacks to asynchronously send values, and there are no return values in that case.
That the Promise constructor itself does take this "resolver" callback (to which it synchronously passes resolve and reject) is in fact an enhancement of the older deferred pattern, and bears no intended similarity to the then callbacks.
var p = new Promise(function(res, rej) { | var def = Promise.Deferred();
setTimeout(res, 100); | setTimeout(def.resolve, 100);
}); | var p = def.promise;
The then callbacks in contrast are classical asynchronous callbacks, with the additional feature that you can return from them. They are being invoked asynchronously to receive values.
p.then(function(val) { … });
To sum up the differences:
Promise is a constructor, while then is a method
Promise takes one callback, while then takes up to two
Promise invokes its callback synchronously, while then invokes its callbacks asynchronously
Promise always invokes its callback,
then might not invoke its callbacks (if the promise is not fulfilled/rejected)
Promise passes the capabilities to resolve/reject a promise to the callback,
then passes the result value / rejection reason of the promise it was called on
Promise invokes its callback for the purpose of executing side effects (call reject/resolve),
then invokes its callbacks for their result values (for chaining)
Yes, both do return promises, though they share that trait with many other functions (Promise.resolve, Promise.reject, fetch, …). In fact all of these are based on the same promise construction and resolve/reject capabilities that also the Promise constructor provides, though that's not their primary purpose. then basically offers the ability to attach onFulfilled/onRejected callbacks to an existing promise, which is rather diametral to the Promise constructor.
That both utilise callbacks is just coincidential - not a historical fluke, but rather coadaption of a language feature.
1: Ideally, you would never need this because all natively asynchronous APIs return promises
Inspired by the previous answers (I'll address the part that was most confusing to me):
The resolve and reject arguments in the Promise constructor are not functions you define. Think of them as hooks that you get to embed into your async operation code (usually you resolve with success response and reject with failure reason) , so that javascript has a way to eventually mark the Promise as Fulfilled or Rejected depending on the outcome of your async operation; once that happens, the appropriate function you defined in then(fun1, fun2) is triggered to consume the Promise (either fun1(success_response) or fun2(failure_reason), depending on whether the Promise is Fulfilled/Rejected). Since fun1 and fun2 are plain old javascript functions (they just happen to take the future outcome of your async operation as arguments), they return values (which can be undefined if you don't explicitly return).
Also see great articles by Mozilla:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The whole point of the promise constructor executor function is to disseminate resolve and reject functions to non-promise-using code, to wrap it and convert it to use a promise. If you wanted to limit this to synchronous functions only, then yes, a return value from the function could have been used instead, but that would have been silly since the useful part is to disseminate the resolver and reject functions to code that actually runs later (way after the return), e.g. to callbacks passed in to some asynchronous API.
Here is the execution flow of Promise.
var p = new Promise((resolve, reject) =>{
console.log("1");
resolve("OK");
});
//The above code creates a promise and execustion starts immediately.
//it happens aynchronously. So the execution will not be blocked.
//Promise exustion will not wait for 'then' call on promise
console.log("2");
//The above line displays 2 on the console.
p.then((result)=>{
console.log("3");
console.log(result);
});
//The above code shoud not block execution. So it may print 4 first
// then 3
console.log("4");

Whats the difference between Q Promise library's .finally() and .done()?

What is the difference between using the Nodejs Q promise library's .finally() and .done() statements.
For example whats the difference between these two?
Q(...)
.then(...)
.finally(); //or fin()
Q(..)
.then()
.done();
promise.done(onSuccess, onError) simply allows you to process resolved value. An additional benefit is that does not imply any error swallowing (as it is the case with promise.then()), it guarantees that any involved exception would be exposed. It also effectively ends the chain and does not return any further promise.
promise.finally(fn) is for registering a task that must be done after a given promise resolves (it doesn't matter whether promise succeeds or fails). Usually, you use it for some kind of cleanup operations e.g. imagine you set up a progress bar, that needs to be hidden after the request is done (no matter if it was successful), then just do promise.finally(hideProgressBar). Additionally promise.finally() returns input promise, so you can return it for further processing.
The difference is in chaining and error handling, and error logging:
Q(...)
.then(...)
.finally();
Here, if the then throws, the finally will still run, but no error will log. In Q finally is run regardless of the .then being successful or not. This is like the finally keyword in JS try/catch/finally. It is also possible to chain additional thens to the chain in this case.
Q(..)
.then()
.done();
Here, done indicates that the promise chain has ended, you can not chain to it any more. If you pass it only an onFulfilled handler it will not run if the then threw, and it will log errors if it ends with an exception.

Node.js Abort chain in Q in different point

I have a pretty long chain of check in Q, and I would to interrupt it when an error rise:
I have looked to How to abort a failing Q promise in Node.JS and other answers on SO, but it seems impossible to me, that can't exist nothing else.
Example
`
Q().then(function(){
return Q.ninvoke(myObject, 'save');
}).fail(functon(err){ // if error
res.status(400).send(err.message);// like duplicate key
}).then(function(){
add object another object to db referenced to myObject
}).fail(functon(err){ // if error
res.status(400).send(err.message);// like connection error
}).then(function(){
do somethinng else
}).done()
`
Obviously, if it can't save the first object, I would not go on through other steps, but I would exit without throwing error and blocking the execution of the server without sending the message to the client.
I tried to add two function to done(OK, REJECTED), but only OK() is called.
I would like to avoid chunking the code in 3 different functions if possible.
As far as I can gather, you don't need to do anything particularly tricky, just understand how success and failure propagate through a .then chain, then exploit this knowledge to get the behaviour you desire.
the chain will continue down the "success" path as long as you keep on having success
the chain will continue down the "fail" path as long as you keep on having failure
if a "success" function throws an error or returns a rejected promise, then the chain will continue down the "fail" path
if a "fail" function returns a value or a fulfilled promise, then the chain will continue down the "success" path.
This behaviour is at the heart of the Promises/A+ standard.
If you were to write your chain with a single, terminal .fail, then (if I understand correctly) you would get the behaviour you seek.
Q().then(function () {
return Q.ninvoke(myObject, 'save');
}).then(function () {
add object another object to db referenced to myObject
}).then(function () {
do somethinng else
}).fail(functon (err) {
res.status(400).send(err.message);
});
Here, failure at any point in the .then chain will cause the propageted promise to drop straight through the rest of the .thens and be caught by the terminal .fail.
This has the advantage over the code in the question, which has multiple interwoven .fails. That pattern can be made to work but you need to introduce a mechanism to suppress multiple "fail" behaviour once the failure has been handled. In unusual circumstances that might be appropriate, but in general it would be regarded as messy.
The only other thing you might need in the fail handler is to distiguish between the different types of failure and act accordingly. That's pretty trivial as the formal variable err can be tested, eg in a switch-case structure. You appear not to need such a test as the action on failure is the same in all cases.

Categories