I'm new in promises and I'm currently trying to understand it. As I knew, Promise.all() has no function to check if one of the promises are rejected. So what I've tried is:
if ( Promise.all( promises ) ) {
console.log( "Everything is resolves!" );
} else {
console.log( "There is a rejected one!" )
}
But this seems to be not working. Is there any simple way to check this? I've found some questions with maps and tried it out but it looks wrong for my implementation.
Call .catch on the Promise call to see if at least one Promise rejects:
Promise.all(promises)
.then((results) => {
// ...
})
.catch((err) => {
// At least one of the Promises rejected (or an error was thrown inside the `.then`)
});
Promises.all( [promises array] ).then(function).catch(errorfunction)
you can do like this:
Promise.all([promises array])
.then((promisevalue) => console.log('returned'))
.catch(error => console.log(error.message));
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Related
I am calling 2 functions using Promise.all function, where I am passing an odd number and an even number. Based on the number I am deciding the success or failure.
const time11=(t) =>{
return new Promise((resolve,reject) =>{
if(t%2==0){
resolve(t)
}else{
reject(t)
}
})
}
// Promise.all
Promise.all([time11(101), time11(1210)])
.then(result => console.log('success',result))
.catch(error=> console.log('error',error))
I expect the output is success 1210 and error 101, but the actual output is error 101.
Promise#allSettled
The Promise.allSettled() method returns a promise that resolves after all of the given promises have either resolved or rejected, with an array of objects that each describes the outcome of each promise.
const time11=(t) =>{
return new Promise((resolve,reject) =>{
if(t%2==0){
resolve(t)
}else{
reject(t)
}
})
}
Promise
.allSettled([time11(101), time11(1210)])
.then(result =>console.log(result));
However, only supported in a few browsers at the moment. Above snippet will only work with latest version of chrome.
Output, will look something like so:
[
{
"status": "rejected",
"reason": 101
},
{
"status": "fulfilled",
"value": 1210
}
]
Here is to separate the errors from the successes.
const time11=(t) =>{
return new Promise((resolve,reject) =>{
if(t%2==0){
resolve(t)
}else{
reject(t)
}
})
}
Promise
.allSettled([time11(101), time11(1210)])
.then(result =>{
const [success, errors] = result.reduce(([success, errors],cur)=>{
if(cur.status === 'fulfilled'){
success.push(cur);
} else {
errors.push(cur);
}
return [success, errors];
}, [[],[]]);
console.log('errors', errors);
console.log('success', success);
});
Promise.all is all or nothing. It resolves once all promises in the array resolve, or reject as soon as one of them rejects. In other words, it either resolves with an array of all resolved values, or rejects with a single error.
Some libraries have something called Promise.when, which I understand would instead wait for all promises in the array to either resolve or reject, but I'm not familiar with it, and it's not in ES6.
In this case, you can resolve all cases, but you must manage different based in the response at the then chain.
const time11=(t) =>{
return new Promise((resolve,reject) =>{
if(t%2==0){
resolve(true) // Changed to boolean
}else{
resolve(false) // Resolved and Boolean
}
})
}
// Promise.all
Promise.all([time11(101), time11(1210)])
.then(isEven => console.log('isEven',isEven))
These are my functions (simplified):
fetchSth: (url) => {return fetch(url)}
parseSth: (res, bot, editMsg) => res.text().then( res => {
return Promise.resolve(['aa', 'bb']);
})
This is my chain:
reqs.fetchSth(url)
.catch(reqs.errInFetch)
.then((res) => reqs.parseSth(res, bot, editMsg)
.then(msg => console.dir(msg)) //prints undefined
)
.then(msg => {
console.dir(msg); //prints undefined
});
Why does it resolve to undefined?
What is returned from reqs.errInFetch? If it's not throwing another error or returning a rejected promise, the chain will continue to resolve to the next then using whatever reqs.errInFetch returned. That's the first place I'd look. If that's the problem you have to decide how you want to handle a fetch error. If it's something your chain can recover from, include that logic in reqs.errInFetch. Otherwise throw an error or return a rejected promise you can catch at the end of the chain.
I want to be able to reject the entire promise chain if anyone of the promise fails in a clean way. I want to "catch" this rejection and send an error notification. I have implemented it the following code:
let reportMetaData = api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id))
.catch(error => {
if (error.status === constants.HTTP_STATUS.GATEWAY_TIMEOUT) {
this.notify.error(this.translate('reports.report_timedout'), this.translate('reports.report_timedout_desc'));
} else {
this.send('error', error);
}
});
let aggregateData = reportMetaData.then(success => {
try {
return api.xmlRequest('GET', success.aggregationUrls.elements[0].url);
} catch (error) {
return Promise.reject();
}
}).then(rawData => {
try {
return JSON.parse('{' + rawData + '}');
} catch (error) {
return Promise.reject();
}
}, error => Promise.reject(error));
let aggregateReport = aggregateData.then(data => {
if (!data || !data.report) {
return Promise.reject();
}
return data.report;
}).catch(error =>{
this.notify.error(this.translate('reports.report_timedout'), error);
});
As you can see, it is super messy and complicated. Is there a way I can simplify this? I want the simplest way to reject the entire promise to fail if anyone promise fails. How do I do that from inside the then function? Also, it seems like the thrown error is bubbling up all the way to chrome console as uncaught error. Why does it bubble up even though I caught it?
You need to use Promise.all() and provide the array of promises as input parameter.
If one of those promises will fail, all the promises will not be resolved.
Here the doc:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
And here a post on SO where you can read about them:
When to use promise.all()?
Try aggregating everything under Promise.all(iterable).
More here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
If this is not quite what you wanted, take a look at Bluebird - fully featured promise library. Here
UPDATE: If you want to reject the entire promise if any of the promises inside the function fails, try implementing:
throw validationError;
Hope it works.
You could use async functions to clean things up a bit. I think you could replace your code with the following.
async function processDataAndReport() {
try {
const data = await api.ajaxGet(api.buildV3EnterpriseUrl('reports' + '/' + params.report_id));
const rawData = await api.xmlRequest('GET', data.aggregationUrls.elements[0].url);
const { report } = JSON.parse(`{${rawData}}`);
} catch(e) {
// send notification
}
}
I have nested promise calls structure as follow:
validateUser()
.then(() => {
getUserInformation()
.then((userInformation) => {
Promise.all([
getUserDebitAccounts(userInformation),
getUserCreditAccounts(userInformation)
])
.then(([drAcc, crAcc]) => {
//do something
})
})
})
.catch(error => {
callback(error);
});
First of all is there a way to simplify these nested calls? As you can see they are structure as per dependency. So this is a most logical way I came up.
Second can I use catch at end to catch all the rejects on all above call. Do I have to add separate catch for each calls?
Third I want to write a mocha test what level of Promise mocking I have to do for these methods some outline will be helpful.
Any suggestion?
Yes, you can and should flatten your chain. To do that you'll need to return the inner promises from the then callbacks, which you will need anyway to make the single catch in the end work.
return validateUser()
.then(getUserInformation)
.then(userInformation =>
Promise.all([
getUserDebitAccounts(userInformation),
getUserCreditAccounts(userInformation)
])
).then(([drAcc, crAcc]) => {
// do something
return …;
})
.catch(error => {
console.error(error);
});
The motivation for this is to be able to catch all possible errors with the ending .catch, even ones that happen in initial synchronous code.
I want to start my promise chain like so:
const bbPromise = require('bluebird');
bbPromise.do(() => {
someTask(); // Could throw
return someVar.doSomeOtherTaskAsync();
})
.then((result) => {
// Do something with result
})
.catch((err) => {
console.log('err: ', err);
});
Is there a function that works like bbPromise.do function? bbPromise.resolve just gives me the whole lambda function that was passed in, unexecuted.
I know I could do something like this:
bbPromise.bind({}).then(() => {
someTask(); // Could throw
return someVar.doSomeOtherTaskAsync();
})
...
or even:
new bbPromise((resolve, reject) => {
someTask(); // Could throw
return someVar.doSomeOtherTaskAsync().then(resolve).catch(reject);
})
...
But these are a little indirect. Is there a good way to start a promise chain by just executing a function that could return a promise, and that has errors caught in the ending .catch?
It sounds like you're looking for Promise.try. Promise.resolve is appropriate when you have a value already and want to build a promise chain from it, but if you want to run some code that may throw, use Promise.try instead.
try takes and executes a function, dealing with any synchronous exception in the same manner as then would. You would end up with something like:
bbPromise.try(someTask).then(() => {
return someVar.doSomeOtherTaskAsync();
}).then((result) => {
// Do something with result
}).catch((err) => {
console.log('err: ', err);
});