Promise fulfilled inspite of rejection - javascript

I am using bluebird settle method to check results for promises regardless of any rejections. In the secondMethod I have rejected the promise still I get isFulfilled() true.
var Promise = require('bluebird');
Promise.settle([firstMethod, secondMethod]).then(function(results){
console.log(results[0].isFulfilled());
console.log(results[1].isFulfilled());
// console.log(results[1].reason());
}).catch(function(error){
console.log(error);
});
var firstMethod = function() {
var promise = new Promise(function(resolve, reject){
setTimeout(function() {
resolve({data: '123'});
}, 2000);
});
return promise;
};
var secondMethod = function() {
var promise = new Promise(function(resolve, reject){
setTimeout(function() {
reject((new Error('fail')));
}, 2000);
});
return promise;
};

I debugged your code and the code within your functions isn't being called. You need to actually call the functions :)
Promise.settle([firstMethod(), secondMethod()]).then(function (results) {
console.log(results[0].isFulfilled()); // prints "true"
console.log(results[1].isFulfilled()); // prints "false"
console.log(results[1].reason()); // prints "fail"
}).catch(function (error) {
console.log(error);
});

Pretty sure isFulfilled is referring to if it is complete or not, regardless of if it's resolved or rejected.
You can use something like isRejected to check to see if the promise has been rejected.

settle API is been deprecated. Refer the github link and this for info. Use reflect API instead as pointed in the documentation.
Secondly, documentation points out with an example:
Using .reflect() to implement settleAll (wait until all promises in an array are either rejected or fulfilled) functionality
var promises = [getPromise(), getPromise(), getPromise()];
Promise.all(promises.map(function(promise) {
return promise.reflect();
})).each(function(inspection) {
if (inspection.isFulfilled()) {
console.log("A promise in the array was fulfilled with", inspection.value());
} else {
console.error("A promise in the array was rejected with", inspection.reason());
}
});
Explanation of above code:
In the above example author is iterating through array of promises using map which returns reflect and inspecting each promise is isRejected or isFulfilled.

Related

Why we are not chaining promises inside each other?

in one of youtube tutorial videos about promises I found following code:
let cleanRoom = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
let removeGarbage = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
let winIcecream = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
cleanRoom().then(function(){
return removeGarbage();
}).then(function() {
return winIcecream();
}).then(function() {
console.log('finished');
})
Why the promises aren't chained like that the every .then word is after the previous promise? I mean, why for example .then is not immediately after removeGarbage() but it is after the cleanRoom().then(), how is it happening that the winIcecream() will run after resolving the removeGarbage promise?
Also do I need to type return declaring every promise like in the code above? If yes, why do I need to do so?
Your initial questions may be answered by rewriting things to variable assignments.
I'm using arrow function syntax to implicitly return the new expression here; if you're using regular functions, then yes, you do have to return the new chained promise if you want to run them in sequence.
const roomCleanedPromise = cleanRoom();
const roomCleanedAndGarbageTakenOutPromise = roomCleanedPromise.then(() => removeGarbage());
const roomCleanedAndGarbageTakenOutAndIcecreamWonPromise = roomCleanedAndGarbageTakenOutPromise.then(() => winIcecream());
const finishedPromise = roomCleanedAndGarbageTakenOutAndIcecreamWonPromise.then(() => console.log('finished'));
However things are easier written using the more modern async/await syntax - the YouTube tutorial you mention is a little outdated, perhaps.
async function cleanRoom() {
console.log('Cleaning room.');
// this could do other async things or just take a while
return {room: 'clean'}; // just to demonstrate a return value
}
async function removeGarbage() {
console.log('Removing garbage.');
// this could do other async things or just take a while
return {garbage: 'removed'};
}
// third function elided for brevity
async function doAllTheThings() {
const roomStatus = await cleanRoom();
const garbageStatus = await removeGarbage();
console.log('finished');
}
The purpose of using a fulfillment handler (the functions passed to then in your example) is to wait for the promise to be fulfilled and then, at that point, do something else.
The goal of that code (apparently) is to wait until the cleanRoom promise is fulfilled, then start the removeGarbage process, and then when that is fulfilled, start the winIcecream process. It's also worth noting that if cleanRoom's promise was rejected instead of being fulfilled, removeGarbage wouldn't happen at all, because it's in a fulfillment handler, not a rejection handler.
If you did this instead:
cleanRoom().then(function() { /*...*/ });
removeGarbage().then(function() { /*...*/ });
winIcecream().then(function() { /*...*/ });
...all three processes would be started immediately and run in parallel (to the extent whatever async process they're modelling can run in parallel with other JavaScript code). There'd be no coordination between them at all.
...how is it happening that the winIcecream() will run after resolving the removeGarbage promise...
then, catch, and finally create and return new promises. Those promises are fulfilled or rejected based on what happens to the promise they were called on and what happens in or is returned by their handler. So for example:
doThis()
.then(function() { return doThat(); })
.then(function() { console.log("done"); });
Let's call the promise from doThis() "Promise A". Calling then on it creates a new promise ("Promise B"), that will either be rejected (if Promise A is rejected) or will call its handler if Promise A is fulfilled. Promise B is resolved to whatever that handler returns. In the code above, suppose Promise A is fulfilled and doThat() returns a promise ("Promise C"). Now, Promise B is resolved to Promise C — whatever happens to Promise C is what will happen to Promise B. If Promise C is fulfilled, Promise B is fulfilled, and the second handler with the console.log is called.
The MDN article on using promises may be helpful.
Your suggestion / thinking I mean, why for example .then is not immediately after removeGarbage() but it is after the cleanRoom().then() is wrong.
Each promise ( .then ) is not execute immediately.
You can take a look at your example ( little edited by me )
const cleanRoom = () => new Promise((resolve, reject) => {
resolve();
});
const removeGarbage = () => new Promise((resolve, reject) => {
resolve();
});
const winIcecream = () => new Promise((resolve, reject) => {
resolve();
})
cleanRoom().then(function(){
console.log('second');
return removeGarbage();
}).then(function() {
return winIcecream();
}).then(function() {
console.log('finished');
})
console.log('first');
You should read more how the event loop works.

JS ES6 Promise Chaining

I'm trying to learn how to use promises, but am having trouble comprehending the chaining. I assume that with this code, both promises will run. Then when I call test.then() it should know that test has resolved and pass the resolve data to then().
Once that function finishes, it goes onto the next then(), repeating the same process with the test2 promise.
However, I can only get it to print out the first promise results, not the second. Any ideas what is missing here?
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
})
.then(test2)
.then(function(data) {
console.log(data);
});
Your first .then call is returning undefined, whereas any subsequent .then is expecting a returned promise. So you'd need to change your code to:
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
return test2;
})
.then(resultOfTest2 => doSomething)
.then(function(data) {
console.log(data);
});
You need to return next promise from the then callback:
test.then(function(data) {
console.log(data);
return test2;
}).then(function(data) {
console.log(data);
});
Summary:
The basic concept of promise chaining with promises is that every then / catch method on a fulfilled promise returns another promise. It works in the following manner:
When a promise is resolved the callback passed in the then method is called. The then method wraps the value which is returned in its callback in a resolved promise and returns this resolved promise.
When a promise is rejected the callback passed in the catch method is called. The catch method wraps the value which is returned in its callback in a rejected promise and returns this rejected promise.
Example:
Before fully understanding the concept of chaining multiple then methods it is important to know what exactly the return values of then and catch are. Take the following example:
let prom1 = new Promise((res, rej) => {
res('res');
});
const resolvedProm1 = prom1.then((val) => {return val});
// setTimeout needed for the promise to actually be resolved
setTimeout(() => console.log(resolvedProm1));
let prom2 = new Promise((res, rej) => {
rej('rej');
});
const resolvedProm2 = prom2.catch((err) => {throw err});
// setTimeout needed for the promise to actually be rejected
setTimeout(() => console.log(resolvedProm2));
We can observe the status of the promises in the chrome devtools:
What basically happens is that in a then or catch callback is the following:
Any value returned in a then or catch callback is wrapped in Promise.resolve() and a new resolved promise is returned.
Any error thrown in a then or catch callback is wrapped in Promise.reject() and a new rejected promise is returned.
Because we are getting returned a rejected or resolved promise object we can repeat the cycle and call the then or catch method on it again. For example:
const prom = new Promise((res, rej) => {
if (Math.random() > 0.5) {
res('success');
} else {
rej('error');
}
});
prom.then((val) => {
return val;
}).then((val) => {
return val
}).then((val) => {
console.log(val)
}).catch((err) => {
console.log('err');
})
This calling of then and catch methods which are executed in their respective order is called promise chaining. It is a very useful technique to make working with asynchronous code easier, especially if multiple asynchronous operations need to be performed which are dependend on each others data.
you need to return the other promise(test2) in the first promise (test1) to allow for chaining:
var test = new Promise(function(resolve, reject){
resolve('done1');
});
var test2 = new Promise(function(resolve, reject){
resolve('done2');
});
test
.then(function(data) {
console.log(data);
return test2;
});
You may also want to try -
let test = new Promise(function(resolve, reject){
resolve('done1');
});
let test2 = new Promise(function(resolve, reject){
resolve('done2');
});
try {
let logOne = test();
let logTwo = test2();
console.log(logOne);
console.log(logTwo);
} catch(error) {
console.error(error);
}
In this way, you can also properly handle any promise dependencies. For example if test one relied on test two's data your could -
try {
let logOne = test();
let logTwo = test2(logOne);
console.log(logOne);
console.log(logTwo);
} catch(error) {
console.error(error);
}

Can I assume that error in a promise will bubble to new Promise and catch that?

I have a function which is going to look up the cache if it finds anything, otherwise then then it will go ahead and fetch the data and set the cache. It's pretty standard. I'm wondering if the error occurs at the most inner function, will it keep bubble up to the outer most Promise? So, I can just have one catch instead of one.
Here's my code.
I'm using Bluebird
var _self = this;
return new Promise(function(resolve, reject) {
_self.get(url, redisClient).then(function getCacheFunc(cacheResponse) {
if(cacheResponse) {
return resolve(JSON.parse(cacheResponse));
}
webCrawl(url).then(function webCrawl(crawlResults) {
_self.set(url, JSON.stringify(crawlResults), redisClient);
return resolve(crawlResults);
}).catch(function catchFunc(error) {
return reject(error); // can I delete this catch
});
}).catch(function getCacheErrorFunc(cacheError) {
return reject(cacheError); // and let this catch handle everything?
});
});
Yes, it is possible to have a single .catch(...) for deeply-nested Promises. The trick: you can resolve a Promise with another Promise. This means that you can refactor your code to:
var _self = this;
_self.get(url, redisClient)
.then(function(cacheResponse) {
if(cacheResponse) {
// Resolve the Promise with a value
return JSON.parse(cacheResponse);
}
// Resolve the Promise with a Promise
return webCrawl(url)
.then(function(crawlResults) {
_self.set(url, JSON.stringify(crawlResults), redisClient);
// Resolve the Promise with a value
return crawlResults;
});
})
.catch(function(err) {
console.log("Caught error: " + err);
});
Note: I also removed your outermost Promise declaration. This was no longer necessary since _self.get(...) already returned a Promise.
Assuming that .get returns a Promise you would write it that way:
var _self = this;
return _self.get(url, redisClient).then(function(cacheResponse) {
if (cacheResponse) {
return JSON.parse(cacheResponse);
} else {
return webCrawl(url).then(function(crawlResults) {
_self.set(url, JSON.stringify(crawlResults), redisClient);
return crawlResults;
})
}
});
There is no need to introduce a new Promise because you already get one from your _self.get

jQuery Deferred promise then

New to the JavaScript Promises and having tough time grasping the concept. It seemed I finally understood, but can't seem to get it working.
Here's a simple try:
first = function(){
var deferred = new $.Deferred();
console.log("first running")
return deferred.promise();
}
second = function(){
console.log("second running..sigh..");
}
$(document).ready(function() {
first().then(second);
});
Second is not being called.
In order for the second function to be called, you need to resolve the deferred returned from the first function:
first = function(){
var deferred = new $.Deferred();
console.log("first running");
deferred.resolve(); // <----------resolve the deferred
return deferred.promise();
}
You can also resolve it with arguments so that whatever its resolved with, will be passed as arguments to your second function. Here's a fiddle that adds a slight delay to the resolve so it mimics asynchronous behavior and resolves with actual data:
http://jsfiddle.net/1k6tLev8/1/
You can think a Promise as a task that, in future, will be processed and a result will be returned to all functions that follow the deferred object.
Promises can have 3 + 1 states:
Pending (The task isn't processed yet)
FullFilled or Resolved (Correctly Processed)
Rejected (Processed but failed)
Settled (indicates that the task is already processed.)
var doSomethingAsync = new Promise(function(resolve, reject) {
window.setTimeout(function() {
resolve('Hello World');
// OR
// reject('You Are Not Welcome')
}, 5000);
});
doSomethingAsync.then(
function(message) {
console.log('After few seconds we can finally tell you:', message)
},
function(error) {
console.log('After few seconds we can finally tell you that: ', error);
}
);
As you can see in the above snippet the then method of a Promise Object accepts TWO params (note, when available, there is a third parameter called notify or progress), the first is called in case of fullfilment, the second in case of rejection.
While the promise is in Pending no callbacks are called!

Dynamic sequence of promise (Q) never go to catch

I have a number of promises (using Q) that i want to call sequentially, here's my code :
// All the promises are called sequentially
var result = promises.reduce(function(promise, item) {
return promise.then(function () {
var obj = toPush.shift();
});
}, Q());
// Check the result
result.then(function() {
// Do something if all of the promises full
}).catch(function() {
// Do something if ONE of the promise is rejected and stop the others
}).finally(function() {
App.network.stopLoader();
});
promises is an array of promise (callback functions)
It works greats, all the promises are done sequentially, but when a promise is rejected, it still go in the then function instead of the catch.
Why ?
I have used this : Break a dynamic sequence of promises with Q
Thanks for your help :)
The reason the catch is never called is because ou don't return anything in this part of the code:
return promise.then(function () {
var obj = toPush.shift();
});
Instead you should try:
return promise.then(function () {
return toPush.shift();
});
If you do:
result.then(console.log)
you should always see undefined which won't be caught.
Hope this helps!
It looks like you just want Q.all:
Q.all(promises).then(function() {
// Do something if all of the promises full
}).catch(function() {
// Do something if ONE of the promise is rejected and stop the others
}).finally(function() {
App.network.stopLoader();
});
According to the documentation, the promise returned by all will be rejected as soon as any of the promises in the array is rejected. (As opposed to allSettled that waits for all the promises to resolve before resolving the returned promise).

Categories