Why do both Promise's then & catch callbacks get called? - javascript

I have the following code and when it's executed, it returns both "rejected" and "success":
// javascript promise
var promise = new Promise(function(resolve, reject){
setTimeout(function(){reject()}, 1000)
});
promise
.catch(function(){console.log('rejected')})
.then(function(){console.log('success')});
Could anyone explain why success is logged?

The then callback gets called because the catch callback is before it, not after. The rejection has already been handled by catch. If you change the the order (i.e. (promise.then(...).catch(...))), the then callback won't be executed.
MDN says that the .catch() method "returns a new promise resolving to the return value of the callback". Your catch callback doesn't return anything, so the promise is resolved with undefined value.

Could anyone explain why success is logged?
In short: a .then following a .catch in a Promise chain will always be executed (unless it itself contains errors).
The theoretical explanation
Your code is actually just a Promise chain which is first executed synchronously setting it up to complete asynchronously afterwards. The Javascript engine will pass on any reject() or Error to the first .then down the chain with a reject callback in it. The reject callback is the second function passed to a .then:
.then(
function (){
//handle success
},
function () {
//handle reject() and Error
})
The use of .catch is just syntactic suger for:
.then(null, function () {
//handle reject() or Error
})
Each of the .then's automatically returns a new Promise which can be acted upon by subsequent .then's (or .catch's which are also .then's).
Visualizing the flow of your promise chain
You can visualize the flow of your code with the following example:
var step1 = new Promise (function (resolve, reject) {
setTimeout(reject('error in step1'), 1000);
})
var step2 = step1.then(null, function () {
// do some error handling
return 'done handling errors'
})
var step3 = step2.then(function () {
// do some other stuff after error handling
return 'done doing other stuff'
}, null)
setTimeout (function () {
console.log ('step1: ', step1);
console.log ('step2: ', step2);
console.log ('step3: ', step3);
console.log();
console.log ('Asynchronous code completed')
console.log();
}, 2000);
console.log ('step1: ', step1);
console.log ('step2: ', step2);
console.log ('step3: ', step3);
console.log();
console.log ('Synchronous code completed')
console.log();
which at runtime will result in the following output in the console:
step1: Promise { <rejected> 'error in step1' }
step2: Promise { <pending> }
step3: Promise { <pending> }
Synchronous code completed
step1: Promise { <rejected> 'error in step1' }
step2: Promise { 'done handling errors' }
step3: Promise { 'done doing other stuff' }
Asynchronous code completed

For those who had a successfully resolved promise and a chain ordered like .then > .catch, but still had both your then and catch called, it may be because your then had an error-throwing bug that you can't see unless you explicitly console the error in your catch. That's one of my pet-peeves with Promises absorbing errors even in strict mode.
const promise = new Promise(resolve => resolve())
.then(() => {
console.log('then');
not.defined = 'This causes the catch to fire even though the original promise resolved successfully.';
})
.catch((e) => {
console.log('catch');
// console.error(e);
});

For me catch() was being called after a succesful promise, and no errors in .then().
The reason was, that I listened to a value that changes with the successful promise, and ran a method.
This method was throwing a silent error, because it was being counted as part of the promise.

Similar to #Timar, For me the reason catch was being called is that "then" contains an exception code. so after executing "then" normally and when it reaches the exception code, it handles the exception in "catch" xD

Related

How to access value from a promise in typescript? [duplicate]

I am trying to wrap my head around promise object in JavaScript. So here I have this little piece of code. I have a promise object and two console.log() on either side of the promise object. I thought it would print
hi
There!
zami
but it printed
hi
zami
There!
Why it is like that? I have zero understanding on how promise works, but I understand how asynchronous callback works in JavaScript. Can any one shed some light on this topic?
console.log('hi');
var myPromise = new Promise(function (resolve, reject) {
if (true) {
resolve('There!');
} else {
reject('Aww, didn\'t work.');
}
});
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
}, function (result) {
// Reject callback.
console.error(result);
});
console.log('zami');
Summary:
A promise in Javascript is an object which represent the eventual completion or failure of an asynchronous operation. Promises represent a proxy for a value which are getting in some point in the future.
A promise can have 3 states which are the following:
Pending: This is the initial state of the promise, the promise is now waiting for either to be resolved or rejected. For example, when are reaching out to the web with an AJAX request and wrapping the request in a promise. Then the promise will be pending in the time window in which the request is not returned.
Fulfilled: When the operation is completed succesfully, the promise is fulfilled. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are succesfully getting data back the promise is said to be fulfilled.
Rejected: When the operation has failed, the promise is rejected. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are getting a 404 error the promise has been rejected.
Promise Constructor:
We can create a promise in the following manner:
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');
Points of interest:
The code inside the promise constructor is synchronously executed.
then method takes as a first argument a callback which is asynchronously executed on promise fulfillment.
then method takes as a second argument a callback which is asynchronously executed on promise rejection. However we are usually using the catch method for this (because this is more verbose), which also takes a callback which is asynchronously executed on promise rejection. catch is essentially the same as then(null, failCallback).
The then callback receives as a first argument the resolved value (the string 'success' in this case).
The catch callback receives as a first argument the rejected value (the string 'Error' in this case).
The finally method receives a callback which is executed on both promise fulfillment and rejection. Here we can write 'cleanup' code which need to be executed always regardless of promise outcome.
Your example:
In your code 'Zami' was printed before 'there' because the log which logged 'there' was in a then callback function. We earlier pointed out that these callbacks are executed asynchronously and thus will be executed last.
Promise execution is asynchronous, which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code.
Basically, your code is doing the following:
Log 'Hi'
Create a promise
Execute the promise
Log 'zami'
Promise is resolved and logs 'There'.
If you want it to print 'Hi there, zami', you will have to
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
console.log('zami');
}, function (result) {
// Reject callback.
console.error(result);
});
Even though you resolved the promised synchronously, the handlers you pass into then get called asynchronously. This is according to the defined specification:
onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack
I would recommend you to understand how event loop works in JavaScript.
take time and watch this Video.
It will clear your doubts.
A Promise is an object representing the eventual completion or failure of an asynchronous operation.
Below is the example of promise:
const post = new Promise((resolve, reject) => {
resolve("Appended from getPostWithPromise()");
});
const getPostWithPromise = function () {
post
.then(function (fulfilled) {
$("body").append("<div>" + fulfilled + "</div>");
})
.catch(function (error) {
console.log(error);
});
}
function getPostWithoutPromise() {
$("body").append("<div>Appended from getPostWithoutPromise()</div>");
}
$(function () {
getPostWithPromise(); // this will print last
getPostWithoutPromise(); // this will print first
$("body").append("<div>Appended directly</div>"); // second
});
you can test it => JavaScript Promises example
for detail understanding you can read this post => https://scotch.io/tutorials/javascript-promises-for-dummies
Promise:
new Promise((resolve, reject) => {
resolve(whateverObject)
reject(whateverErrorObject)
})
It is just object that can be chained with then()
You also can make promise! you can return whatever object in that success parameter (resolve) and error parameter (reject)
so very simple concept bro!
Promises are objects.
Each promise object has a then method.
The then method of the promise object accepts a function as a first parameter.
If we call the then method of a promise, the callback function will be executed once the promise gets resolved.
Flow of execution
const promiseObj = new Promise((res, rej) => {
console.log("Promise constructor are synchronously executed");
res("Hii Developer");
})
const callbackFunction = (resolvedValue) => console.log("Resolved Value ", resolvedValue);
promiseObj.then(callbackFunction);
console.log("I am the executed after the constructor");
In the above example, we have created a promise object using the Promise constructor.
The constructor function is synchronously executed.
After creating the promise object, we are calling the then method of the promise object. We have passed a callback function in the first argument of the then method. This callback function will be executed once the promise gets resolved and the stack of the js engine gets empty.
Promise is a object that represents the completion or failure of a event . Promise is a asynchronous thing in JS which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code. So it wont be executed simultaneously. It would take time to either complete or fail for a given task and then execution.
In your Case
log'Hi'.
First your mypromise variable will store a promise object i.e either rejected or resolved(for this, it would take time)
But JS engine will execute further code first then the asynchronous task. SO u will get 'zami'.
once the promise resolved or rejected. It will be called or used wherever it is used in the code. In this case ,it is resolved and log 'there!' in console.
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');

Node JS: Not calling promise reject() callback stops the execution of the program

It seems I misunderstand the Promise mechanism. In the following code:
async function CreateSession()
{
var sessionId = await new Promise((resolve, reject) => {
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
log.debug("Session created successfully")
resolve(body["session-id"]);
}
else
{
log.error("Failed to create session:");
log.error(error);
// reject(error);
}
});
});
log.debug(`Session Id: ${sessionId}`);
return sessionId;
}
The reject() is commented on purpose to understand the mechanism.
When calling the above CreateSession() function as follows and making sure an error is happenning:
async function MyFunction()
{
var sessionId = await CreateSession();
AnotherCode();
}
The entire program stops, the code after await in CreateSession is never reached, AnotherCode() is never called, and even if I put a handler for uncaught exception it doesn't catch any error.
My questions:
Why does the program stops when reject() is not called?
If it's an error why it is not called by the handler for uncaught exceptions?
How do I ignore the an error when a promise fails to run its code?
Why does the program stops when reject() is not called?
Because of the await. The program waits for the promise to either resolve or reject. It can't detect somehow that the code inside the promise constructor has finished executing (even if it could - what should be the "standard" behavior?) and there is no more code to come.
From the MDN:
An async function can contain an await expression that pauses the execution of the async function to wait for the passed Promise's resolution, then resumes the async function's execution and evaluates as the resolved value.
For some "under the hood" insights, you might want to look at the ES5 code generated by transpilers like Babel (IIRC it uses generators to handle this).
If it's an error why it is not called by the handler for uncaught exceptions?
The program doesn't know that error is an error if it's neither thrown nor passed using reject.
How do I ignore the an error when a promise fails to run its code?
Either resolve (instead of reject) or reject and do the classical try/catch around the await code
For a start you're mixing 2 concepts that achieve the same thing, the creation of a Promise. You are mixing async/await and new Promise.
That makes it actually like you have 2 chained Promises.
Why does the program stops when reject() is not called?
Because you are returning a Promise and that by itself demands that either a resolve or a reject callbacks are called.
If it's an error why it is not called by the handler for uncaught exceptions?
There is no actual error, the only thing that happens is that your if clause is not met.
How do I ignore the an error when a promise fails to run its code?
Again, the Promise does not fail to run it's code, you're failing to understand the concept.
To make it easier either use something like :
function CreateSession(){
return new Promise((resolve, reject) => {
if( <yourconditionhere> ){
resolve(res);
}else{
reject(error);
}
});
}
CreateSession
.then((res) => {
// code to execute in case of success (resolve)
// receiving as argument the argument of the resolve call.
AnotherCode();
})
.catch( error => {
// code to execute in case of non-success (reject)
// receiving as argument the argument of the reject call.
});
or
async function CreateSession(){
let res = await request(options, function (error, response, body) {
if( <yourconditionhere> ){
return ...;
}else{
return ...;
}
}
return res;
}
async function MyFunction()
{
var sessionId = await CreateSession();
AnotherCode();
}

Javascript Promises Chaining Multiple Errors

How come that all my Resolved Callbacks are properly executed but only
1 Error Callback is being run ?
In the example here if longOperation(true) I get only one error, while when run with false I get the two resolved messages. In my understanding each .then returns a new promise which is in the error state for the second .then error callback registration
This example is written using Typescript !
function longOperation(error) {
return new Promise < any > ((resolve, reject) => {
if (error) {
reject("Error")
} else {
setTimeout(function() {
resolve(true)
}, 1000)
}
})
}
let op = longOperation(true);
op
.then(result => {
console.log("Resolved #1")
}, undefined)
.then(result => {
console.log("Resolved #2")
}, undefined)
.then(undefined, error => {
console.log("Error1")
})
.then(undefined, error => {
console.log("Error2")
})
The first error handler catches the error, just like a regular catch block. If you want the chained promise to be rejected, you have to rethrow the error:
Promise.reject().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(null, e => {
console.log(3);
throw e; // <= rethrow here
}).then(null, e => {
console.log(4);
});
Promises can "recover".
The error will propagate down the chain of ".then"s until it finds an error callback. When it does it will execute the error callback and pass the return value down to the next promise's resolve method.
So only the next closest error callback to the promise will get executed.
If you want to catch all possible errors along the chain just put your error callback at the end of the chain and all errors will be handled by it.
In your code example you are actually creating 5 promises. The original one and 1 for each ".then". The 2nd and 3rd only have an onResolved method and the last two only have and onRejected method.
This is how it will be executed:
1st Promise(op): I just rejected. I see I have a deferred promise with no onRejected callback. So I'll just call it's reject method with the same value I rejected with.
2nd Promise: The previous promise called my reject method and I also have a deferred promise with no onRejected callback. So I'll just call it's reject method with the same value I rejected with.
3rd Promise: The previous promise called my reject method. I have a deferred promise too, but mine does have an onRejected callback. I,ll call the callback with the value I rejected with, and I'll call my deferred promise's resolve method with the callback's return value.
4th Promise: The previous promise called my resolve method. I have a deferred promise, but it doesn't have an onResolved callback so I'll just call it's resolved method with the value I resolved with.
5th Promise: The previous promise called my resolve method. I resolved and did nothing more because I have no deferred promise.

Understanding JavaScript promise object

I am trying to wrap my head around promise object in JavaScript. So here I have this little piece of code. I have a promise object and two console.log() on either side of the promise object. I thought it would print
hi
There!
zami
but it printed
hi
zami
There!
Why it is like that? I have zero understanding on how promise works, but I understand how asynchronous callback works in JavaScript. Can any one shed some light on this topic?
console.log('hi');
var myPromise = new Promise(function (resolve, reject) {
if (true) {
resolve('There!');
} else {
reject('Aww, didn\'t work.');
}
});
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
}, function (result) {
// Reject callback.
console.error(result);
});
console.log('zami');
Summary:
A promise in Javascript is an object which represent the eventual completion or failure of an asynchronous operation. Promises represent a proxy for a value which are getting in some point in the future.
A promise can have 3 states which are the following:
Pending: This is the initial state of the promise, the promise is now waiting for either to be resolved or rejected. For example, when are reaching out to the web with an AJAX request and wrapping the request in a promise. Then the promise will be pending in the time window in which the request is not returned.
Fulfilled: When the operation is completed succesfully, the promise is fulfilled. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are succesfully getting data back the promise is said to be fulfilled.
Rejected: When the operation has failed, the promise is rejected. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are getting a 404 error the promise has been rejected.
Promise Constructor:
We can create a promise in the following manner:
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');
Points of interest:
The code inside the promise constructor is synchronously executed.
then method takes as a first argument a callback which is asynchronously executed on promise fulfillment.
then method takes as a second argument a callback which is asynchronously executed on promise rejection. However we are usually using the catch method for this (because this is more verbose), which also takes a callback which is asynchronously executed on promise rejection. catch is essentially the same as then(null, failCallback).
The then callback receives as a first argument the resolved value (the string 'success' in this case).
The catch callback receives as a first argument the rejected value (the string 'Error' in this case).
The finally method receives a callback which is executed on both promise fulfillment and rejection. Here we can write 'cleanup' code which need to be executed always regardless of promise outcome.
Your example:
In your code 'Zami' was printed before 'there' because the log which logged 'there' was in a then callback function. We earlier pointed out that these callbacks are executed asynchronously and thus will be executed last.
Promise execution is asynchronous, which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code.
Basically, your code is doing the following:
Log 'Hi'
Create a promise
Execute the promise
Log 'zami'
Promise is resolved and logs 'There'.
If you want it to print 'Hi there, zami', you will have to
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
console.log('zami');
}, function (result) {
// Reject callback.
console.error(result);
});
Even though you resolved the promised synchronously, the handlers you pass into then get called asynchronously. This is according to the defined specification:
onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack
I would recommend you to understand how event loop works in JavaScript.
take time and watch this Video.
It will clear your doubts.
A Promise is an object representing the eventual completion or failure of an asynchronous operation.
Below is the example of promise:
const post = new Promise((resolve, reject) => {
resolve("Appended from getPostWithPromise()");
});
const getPostWithPromise = function () {
post
.then(function (fulfilled) {
$("body").append("<div>" + fulfilled + "</div>");
})
.catch(function (error) {
console.log(error);
});
}
function getPostWithoutPromise() {
$("body").append("<div>Appended from getPostWithoutPromise()</div>");
}
$(function () {
getPostWithPromise(); // this will print last
getPostWithoutPromise(); // this will print first
$("body").append("<div>Appended directly</div>"); // second
});
you can test it => JavaScript Promises example
for detail understanding you can read this post => https://scotch.io/tutorials/javascript-promises-for-dummies
Promise:
new Promise((resolve, reject) => {
resolve(whateverObject)
reject(whateverErrorObject)
})
It is just object that can be chained with then()
You also can make promise! you can return whatever object in that success parameter (resolve) and error parameter (reject)
so very simple concept bro!
Promises are objects.
Each promise object has a then method.
The then method of the promise object accepts a function as a first parameter.
If we call the then method of a promise, the callback function will be executed once the promise gets resolved.
Flow of execution
const promiseObj = new Promise((res, rej) => {
console.log("Promise constructor are synchronously executed");
res("Hii Developer");
})
const callbackFunction = (resolvedValue) => console.log("Resolved Value ", resolvedValue);
promiseObj.then(callbackFunction);
console.log("I am the executed after the constructor");
In the above example, we have created a promise object using the Promise constructor.
The constructor function is synchronously executed.
After creating the promise object, we are calling the then method of the promise object. We have passed a callback function in the first argument of the then method. This callback function will be executed once the promise gets resolved and the stack of the js engine gets empty.
Promise is a object that represents the completion or failure of a event . Promise is a asynchronous thing in JS which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code. So it wont be executed simultaneously. It would take time to either complete or fail for a given task and then execution.
In your Case
log'Hi'.
First your mypromise variable will store a promise object i.e either rejected or resolved(for this, it would take time)
But JS engine will execute further code first then the asynchronous task. SO u will get 'zami'.
once the promise resolved or rejected. It will be called or used wherever it is used in the code. In this case ,it is resolved and log 'there!' in console.
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');

Promises: is .done() executed always even if .catch() is?

My Promise issue
I am new to Promises and I've been reading the Q Documentation, where it says:
When you get to the end of a chain of promises, you should either return the last promise or end the chain.
I have defined a Promise in my code the Q.Promise way, with the following console.logs to log out an execution trace:
function foo(){
return Q.Promise(function(resolve, reject) {
doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
.then(function() {
console.log('2');
return doSomething2();
})
.then(function() {
console.log('3');
return doSomething3();
})
.catch(function(err) {
console.log('catch!!');
reject(err);
})
.done(function() {
console.log('done!!');
resolve();
});
});
}
In case every doSomethingN() executes correctly, everything works as intended and I get the expected trace:
1
2
3
done!!
But in case any of the doSomethingN() fails:
foo() works correctly, because the error function callback is the one that runs whenever a reject(err) occurs:
foo().then(function() { /* */ }, function(err) { /* this runs! */ });
And I get the following trace (ie. when doSomething1() fails):
1
catch!!
done!!
My question
What I thought at first was the following:
Okay, let's handle the chaining success and failure in both: .done() and .catch() methods. If everything goes well .done()'s callback will be executed and the promise will be resolved. In case there's an error at any point, .catch()'s callback will be executed and the promise will be rejected - and because of that, done() won't be executed.
I think I am missing something about how the .done() works... because by having a look at my logging trace, I realized that .done() seems to be executing always - whether there is an error and .catch() is executed or not - and that is what I wasn't expecting.
So, after that, I removed .done()'s callback and now foo():
works if there's an error during the chain execution
does not work if everything works correctly
What should I reconsider and how could/should I make it work?
catch(cb) is just an alias for then(null, cb), and you've actually fixed an error in catch, so flow naturally turned to success result in done.
If you want to just decorate the error in catch, you should rethrow the error afterwards, e.g. proper passthru may look as:
catch(function (err) {
console.log(err);
throw err;
});
Still your example doesn't make much sense. You should never use done, when you return a promise. If you want to resolve initialized promise with internally created chain of promises, you should just resolve it as:
resolve(doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
....
.then(function() {
console.log('N');
return doSomethingN();
}));
There's no need for internal error handling, leave that to consumer of promise which you return.
And other point. If when creating new promise you know it will be resolved with other one, then there's no logical reason to create such promise, just reuse one you planned to resolve with. Such error was also coined as deferred anti-pattern
You should consider doing this:
function foo() {
// Calling .then() on a promise still return a promise.
// You don't need Q.Promise here
return doSomething()
.then(function(doSomethingResult) {
console.log('1');
return doSomething1();
})
.then(function(doSomething1Result) {
console.log('2');
return doSomething2();
})
.then(function(doSomething2Result) {
console.log('3');
return doSomething3();
});
}
foo()
.then(function(fooResult) {
console.log(fooResult); // fooResult should be what is returned by doSomething3()
})
.catch(function(err) {
console.error(err); // Can be thrown by any
})
.done(function() {
console.log('I am always executed! error or success');
});
If you want to return a promise, in most cases it does not make much sense to use catch (unless you want to recover potential errors). It never make sense to use done in a method returning a promise. You would rather use these methods at the very end of the chain.
Notice that doSomethingX() can return either a value, or a promise, it will work the same.
You can make it work by resolving promise in your last then callback.
function foo(){
return doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
.then(function() {
console.log('2');
return doSomething2();
})
.then(function() {
console.log('3');
return doSomething3();
})
}
Consider using bluebird for promises. It has many useful features as compared to any other promise library. You may find it difficult to begin it, but once you get hold of it you're going to love it.

Categories

Resources