This question already has answers here:
if-else flow in promise (bluebird)
(3 answers)
Closed 4 years ago.
I have a conditional if statement who's logic needs to be wrapped in a promise as the logic after if can only be executed after it.
// WRAP 'if' statement below IN A PROMISE
if (a) { // could be true or false. If false, resolve the promise
// logic here
}
.then(
// execute logic after if here
)
I'm new to nodejs and am trying to wrap my head around this. How can I solve this ?
Just wrap it into a new Promise:
new Promise((resolve, reject) => {
if(a){
reject("error");
} else {
resolve(yourData);
}
})
.then(data => {
// Do stuff
})
.catch(err => {
// You should catch here an error rejected above
})
The question is unclear a bit. Here is answer according to what I understand. You can not run code inside promise once it is resolved or rejected.
new Promise((res, rej) => {
if (false) {
}
res();
console.log('More code') // this will not run
}).then(() => {
console.log('This will run')
})
Related
This question already has answers here:
Weird behavior with Promise throwing "Unhandled promise rejection" error
(1 answer)
Uncaught (in promise)
(2 answers)
How is PromiseRejectionEvent triggered?
(2 answers)
UnhandledPromiseRejectionWarning after clearTimeout [duplicate]
(1 answer)
Closed 5 months ago.
I've recently encountered a weird behavior with nodejs. I'll explain with the following example:
let's say we have two functions, foo and bar, foo creates a promise, calls .finally() on it, and returns it. bar on the other hand, wraps the promise with a try/catch.
const foo = () => {
const promise = new Promise((resolve, reject) => {
reject('my-error');
});
promise.finally(() => {
console.log('at foo');
});
return promise;
}
const bar = async () => {
try {
const result = await foo();
} catch (e) {
console.log('at bar: ', e);
}
}
bar();
the output would be:
at foo
at bar: my-error
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "my-error".] {
code: 'ERR_UNHANDLED_REJECTION'
}
From the output, we can see that the error is handled by bar function, yet an UnhandledPromiseRejection error is thrown.
However, if we replace .finally() with .catch() not such error happen.
const foo = () => {
const promise = new Promise((resolve, reject) => {
reject('my-error');
});
promise.catch(() => {
console.log('at foo');
});
return promise;
}
I'm not sure what's happening over here; I'd appreciate it if someone could help me visualize what's happening.
then, catch, and finally create new promises that are resolved to the promise you call them on and the result of the handler function you pass into them. (If resolved to is slightly unfamiliar, see my blog post on promise terminology.) The unhandled rejection is from the promise created by finally, which was rejected because the promise it was resolved to was rejected. Nothing in your code handles the rejection of that promise, just the other one.
If you want to use finally on the promise created in foo, return the resulting promise instead of the original one:
const foo = () => {
const promise = new Promise((resolve, reject) => {
reject('my-error');
});
// vvvvvv−−−−−−−−−−−−−−−−−−−−−−
return promise.finally(() => {
console.log('at foo');
});
}
const bar = async () => {
try {
const result = await foo();
} catch (e) {
console.log('at bar: ', e);
}
}
bar();
It's not much I discovered Javascript Promise.
However I found out a behaviour I couldn't understand concerning the nesting of (new or returned) Promise inside Promises
That's the background (extPromiseX is a third-party function returning Promise):
Case 1:
function myAction(param) {
return extPromise1(sql).then((result) => {
[...]
return extPromise2(sql2).then((result) => {
[...]
return extPromise3(sql3);
})
});
}
// Main Process
myAction(...)
.then(() => {
console.log('Process Terminated');
}).catch((error) => {
console.error('Exit with error', error);
});
Now, as expected, I got from the console, in
1) extPromise1 completed
2) extPromise2 completed
3) extPromise3 completed
4) Process Terminated
Case 2:
function myAction(param) {
return new Promise(function() {
if (itsAllOkWithInputs) {
// Some sync code here
return extPromise1(sql).then((result) => {
[...]
return extPromise2(sql2).then((result) => {
[...]
return extPromise3(sql3);
})
})
} else {
throw 'Something went wrong';
}
});
}
// Main process
myAction(...)
.then(() => {
console.log('Process Terminated');
}).catch((error) => {
console.error('3) --> Exit with error', error);
})
In this second case extPromises are executed but the very first Promise remains pending (confirmed by debug). So the console shows:
1) extPromise1 completed
2) extPromise2 completed
3) extPromise3 completed
I empirically realized that I had to change myAction function as follow for the code to work:
function myAction(param) {
return new Promise(function(resolve, reject) {
if (itsAllOkWithInputs) {
// Some sync code here
let ep = extPromise1(sql).then(...);
resolve(ep);
} else {
throw 'Something went wrong';
}
});
}
My question:
I thought returning a promise inside another parental one would make
the parent resolving with the results of the child. This is the case
inside the then code block applied to the external promises. Why
this is not valid for the new Promise case?
Because .then is meant to chain promises. You can return a Promise from inside the then callback, and then itself will return a new Promise.
The Promise constructor is supposed to construct a Promise from an underlying callback. If you return a Promise from inside a Promise constructor, you are doing something wrong conceptually. And that's why it does not work.
function myAction(param) {
if (itsAllOkWithInputs) {
return extPromise1(sql).then(...);
} else {
return Promise.reject('Something went wrong');
}
}
// OR
async function myAction(param) {
if (itsAllOkWithInputs) {
await extPromise1(sql);
} else {
throw 'Something went wrong';
}
}
new Promise(function() {
You are not using neither resolve nor reject arguments (you actually even haven't declared them), so the promise will never get resolved or rejected. All other stuff is irrelevant.
If your function returns promise, you have to simply call it and return a result. If you don't know whether the function return promise or just a value, you can wrap it's call into Promise.resolve, but not in new Promise.
This question already has an answer here:
How to get a value from a "Promise" object
(1 answer)
Closed 4 years ago.
I'm trying to use the mongoose to try to fetch all the records under the Profile Schema using the find() method. The code looks fine to me and when I console.log the code block, it returns Promise { <pending> }.
I tried different approaches with no hope. Any help would be appreciated.
Thanks,
Here is my Code:
return Profile.find()
.then(profiles => {
return profiles.map(profile =>{
return {
...profile._doc
};
});
}).catch(err => {
//console.log(err);
throw err;
})
That would be because the promise is in pending state.If you need the data after the promise has been resolved you would have to add a then callback.
function getProfiles(){
return Profile.find()
.then(profiles => {
return profiles.map(profile =>{
return {
...profile._doc
};
});
}).catch(err => {
//console.log(err);
throw err;
})
}
getProfiles().then(profiles => console.log('profiles',profiles))
This question already has answers here:
Asynchronous exception handling with bluebird promises
(3 answers)
Closed 4 years ago.
If there is a promise with an asynchronous function in it and if in the asynchronous function an error happens the promise doesn't catch but throws an error and crashes the application, which I don't understand.
Obviously I would like to handle the error, do you know why does the promise behave like this and what would be a way around it?
thanks
// this promise will have an error since param is not defined,
// and the promise won't be caught
function randomPromise(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
param[0] = 11;
}, 2000);
});
}
randomPromise()
.then(() => {
console.log('nothing');
})
.catch((e) => {
console.log('with set timeout or any async function in the promise, the error caused by \'param[0] = 11;\' wont bring the control here into the catch block just throws an error and crashes the application');
console.log(e);
});
// this promise will have an error since param is not defined
// but the promise will be caught
function randomPromiseGoesToCatchBlock(param) {
return new Promise((resolve, reject) => {
param[0] = 11;
});
}
randomPromiseGoesToCatchBlock()
.then(() => {
console.log('nothing');
})
.catch((e) => {
console.log('without the setTimeout function or any async function the error caused by \'param[0] = 11;\' brings the control here into the catch block');
console.log(e);
});
Errors that are thrown inside a Promise constructor and that occur asynchronously need to be explicitly try/catched so that reject can be called, so that the Promise control flow can be transferred to the Promise's catch. For example:
// this promise will have an error since param is not defined, and the promise wont be catched
function randomPromise(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
param[0] = 11;
} catch(e) {
reject(e);
}
}, 2000);
});
}
randomPromise()
.catch((e) => {
console.log(e.message);
});
Otherwise, neither resolve nor reject will be called, and the error was asynchronous, so the thread the Promise was created on has already ended, so the interpreter doesn't know that the thrown error should reject that Promise without you explicitly telling it to.
In contrast, errors thrown synchronously inside a Promise constructor will automatically result in the constructed Promise rejecting immediately.
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 5 years ago.
I want to use Mongoose's bulk operation for upserting transactions. For each of my transactions I want to process them in a loop and within that loop I need to use a promise. After that promise resolved, I want to add the upsert to the bulk.
My problem here is, that although I await for every promise to finish, the bulk is executed at the end of the function before any of the promises is resolved. What am I doing wrong or how can I fix this?
const bulkTransactions = Transaction.collection.initializeUnorderedBulkOp();
transactions.forEach( async (transaction: any) => {
// do some suff, fill transaction_data
await Utils.processTransactionType(transaction).then((action: any) => {
if (action) {
// do other stuff
}
bulkTransactions.find({_id: hash}).upsert().replaceOne(transaction_data);
}).catch((err: Error) => {
// log error
});
});
await bulkTransactions.execute().catch((err: Error) => {
// log error
});
As far as I know, when using await, you no longer use the then return value:
const bulkTransactions = Transaction.collection.initializeUnorderedBulkOp();
transactions.forEach( async (transaction: any) => {
// do some suff, fill transaction_data
let action = await Utils.processTransactionType(transaction);
if (action) {
// do other stuff
}
bulkTransactions.find({_id: hash}).upsert().replaceOne(transaction_data);
});
await bulkTransactions.execute().catch((err: Error) => {
// log error
});