Rejected promise still call to the next .then() - javascript

Here is a promise chain that rejects 100%. I expect the first console.log to print, but after that because of the rejected promise it should skips to .catch at the end
function stringProcessor(string)
{
return new Promise((resolve, reject) => {
console.log(`Calling ${string}`)
reject(`Rejected ${string}`)
});
}
exports.concat = functions.https.onRequest((request, response) => {
return stringProcessor("foo")
.then(stringProcessor("bar"))
.then(stringProcessor("hello"))
.then(response.send("no problem!"))
.catch(e =>
{
console.log("CAUGHT : " + e)
response.send("not ok")
})
})
However the output log is
info: User function triggered, starting execution
info: Calling foo
info: Calling bar
info: Calling hello
info: CAUGHT : Rejected foo
info: Execution took 15 ms, user function completed successfully
error: (node:67568) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Rejected bar
error: (node:67568) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:67568) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Rejected hello
Not only that everything has been called sequentially, also I have been warned about uncaught promise even if the CAUGHT line clearly prints.

You need to pass function which returns promise in then:
return stringProcessor("foo")
.then(() => stringProcessor("bar"))
.then(() => stringProcessor("hello"))
// ...
In your example you are not passing functions, but promises.

Related

Unhandled promise rejection nodejs

I am trying to use openweather-apis to connect to a dialogflow agent. I am new to promises and I keep getting the warning UnhandledPromiseRejectionWarning and I'm not sure on how to fix this.
Currently I have 2 files weather.js, which makes the api call
const api = require("openweather-apis")
api.setAPPID(process.env.API_KEY)
api.setUnits("metric")
module.exports = {
setCity: function(city) {
api.setCity(city)
},
getWeather: function() {
return new Promise(function(resolve, reject) {
api.getTemperature(function(err, temp) {
if (err) reject(err)
resolve(temp)
})
})
}
}
And I make use of weatherinCity.js, which retrieves the city from the agent, calls the calling function and then sends a response to the user.
const weather = require("../../weather")
module.exports = {
fulfillment: function(agent) {
const city = agent.parameters.geo_city
weather.setCity(city)
weather.getWeather().then(function(temp) {
agent.add(
"It is ${temp} degrees Celcius in ${city}"
)
}).catch(() => {
console.error("Something went wrong")
})
}
}
full error message:
(node:2896) UnhandledPromiseRejectionWarning: Error: No responses defined for platform: DIALOGFLOW_CONSOLE
at V2Agent.sendResponses_ (C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\v2-agent.js:243:13)
at WebhookClient.send_ (C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\dialogflow-fulfillment.js:505:17)
at C:\Users\Coen\Desktop\ciphix-ca-case\node_modules\dialogflow-fulfillment\src\dialogflow-fulfillment.js:316:38
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2896) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. 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(). To terminate the node process on unhandled
promise rejection, use the CLI flag `--unhandled-rejections=strict` (see
https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).
(rejection id: 1)
(node:2896) [DEP0018] DeprecationWarning: Unhandled promise rejections
are deprecated. In the future, promise rejections that are not handled
will terminate the Node.js process with a non-zero exit code.
This error indeed happened because this code fails to handle the Promise Rejection. While I'm not sure which Promise Rejection that failed to handle, but based on this and this GitHub discussions. It seems you need to return the agent.add() function.
I recommend trying async-await style with the consequence that you have to add a try catch block
module.exports = {
fulfillment: async function(agent) {
try {
const city = agent.parameters.geo_city
weather.setCity(city)
let temp = await weather.getWeather()
agent.add(
"It is ${temp} degrees Celcius in ${city}"
)
} catch (err) {
console.error("Something went wrong")
console.error(err)
}
}
}
Every error that is thrown on the try block should be caught in a catch block. Don't forget to add async before the function.
it will not solve your problem but generally speaking, i would add "return" after if(err). because otherwise the call to resolve would be done. in your particular case it will do no harm, as because of the nature of promises it will be ignored. but if you had written anything between reject and resolve it would have been executed.
// best practice
if (err) return reject(err)
for your problem, i've just tried this fast test to convice myself that even throws are catched by .catch() so i think you must be running a bad/old nodejs version, or the code you provided is not complete, and the failure is elsewere. I dont see any line pointing to your own code in the log O_o (only node_modules).
which nodejs version is it ?
var p = new Promise((resolve, reject) => {
throw new Error('test');
resolve('ok')
})
p.then(console.log).catch(function(err) {
console.error('err', err)
});

How to throw an exception from a Promise to the Caller without an UnhandledPromiseRejectionWarning

Consider this database query handler that does contain a catch block:
async function dml(pool, sql, expected = -1) {
p(sql)
let rowCnt = await pool.query(sql)
.then(r => {
if (expected >= 0 && r.rowCount != expected) {
throw `DML [${sql}] had wrong number of results: ${r.rowCount} vs expected=${expected}`
} else {
return r.rowCount
}
})
.catch(err => {
msg = `Query [${sql}] failed: ${err}`;
printError(msg,err)
throw msg // THIS is the problem. It generates UnhandledPromiseRejection
}
return rowCnt
}
The thrown exception is intended to be caught by the caller here:
async function handleClip(data) {
..
// calling code
try {
// ...
let cnt = db.dmlClips(sql, 1) // Throw() happens in this invocation
debug(`Update count is ${cnt}`)
return rcode
} catch (err) {
// WHY is the thrown exception not caught here??
let msg = `Error in handleClip for data=${data.slice(0,min(data.length,200))}`;
error(msg,err);
}
But the above structure is not acceptable apparently: the following serious warning is generated:
(node:39959) UnhandledPromiseRejectionWarning: Query [insert into clip ...] failed: error: role "myuser" does not exist
at emitUnhandledRejectionWarning (internal/process/promises.js:170:15)
at processPromiseRejections (internal/process/promises.js:247:11)
at processTicksAndRejections (internal/process/task_queues.js:94:32)
(node:39959) UnhandledPromiseRejectionWarning: Unhandled promise rejection.
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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict`
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:39959) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.js process with
a non-zero exit code.
at emitDeprecationWarning (internal/process/promises.js:180:11)
at processPromiseRejections (internal/process/promises.js:249:13)
at processTicksAndRejections (internal/process/task_queues.js:94:32)
So how does this need to be set up ? Note there is a related question here: how to properly throw an error if promise is rejected? (UnhandledPromiseRejectionWarning) . But for that question the asker did not have any exception handler/catch block.
You need to use await when you're calling the function db.dmlClips(sql, 1) so that it waits for the promise to be resolved/rejected. Change the line to let cnt = await db.dmlClips(sql, 1).
It looks like the try-catch block from which you are invoking db.dmlClips isn't inside an async function. Try-catch declared in functions without async keywords won't catch a promise rejection.

UnhandledPromiseRejectionWarning when using .reduce

const sendData = (response, language, locale) => {
try {
console.log(response.reduce((prev, curr) => prev + curr.confirmed, 0));
} catch (error) {
console.error('error');
}
};
and my fetch function:
const fetchGeneralData = async (param) => {
try {
let res = await axios.get(
`https://localhost/api/${param}`,
);
msg.reply(sendData(res.data.results), language, momentLocale);
} catch (error) {
msg.reply(language.errorMessage);
console.error(error, 'Error on fetchGeneralData');
}
};
The console.log shows me the correct value but for some reason, I still getting the errors.
I have tried adding async/await inside sendData but it did not work. My fetchGeneralData func works fine when i'm trying to return the date without modify it.
Here is the full message:
(node:5500) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: t.match is not a function
(node:5500) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 1)
(node:5500) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

node: add catch-function to promise after construction

Consider this code:
var p = new Promise(function(resolve, reject){
console.log("run");
setTimeout(reject, 5);
});
p.catch(function() {
console.log("cought!");
});
p.then(function() {
console.log("then!");
});
Output (browser):
run
cought!
Here, in the browser it behaves like expected. Bun ran as a node-script I get:
run
cought!
(node:13927) UnhandledPromiseRejectionWarning: undefined
(node:13927) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 1)
(node:13927) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
So the rejection got catched, but node is still complaining - why that?
I could chain everything together as suggested here and here:
new Promise(function(resolve, reject){
console.log("run");
setTimeout(reject, 5);
}).then(function() {
console.log("then!");
}).catch(function() {
console.log("cought!");
});
Output (browser and node):
run
cought!
In my usecase I can't use this solution, because I have a factory-function which builds the Promise. The catch- and then-functions shall be attached by the factory's caller.In case of then-function it works, but not for catch. How could I avoid this warning?
Promises are multicast, so each time you call .then or .catch you get a new promise object (chain) back. That is, p.then and p.catch both return their own separate promise objects. This means that there is no catch path for p.then.
If chaining the promises together is not possible, then you'll have to handle the error in the new promise chain created by .then. You can swallow this exception if you so choose, but it is a separate exception:
p.then(function() {
console.log("then!");
}).catch(() => {});
I am using Async Await to solve this problem hope it helps, works fine in my computer.
const iReturnPromise = () => {
return new Promise((resolve, reject) => {
console.log("run");
setTimeout(reject, 5);
});
}
async function displayPromiseResults() {
try {
await iReturnPromise();
console.log('!then');
}
catch(ex) {
console.log("cought!");
}
}
displayPromiseResults();

UnhandledPromiseRejectionWarning even when there is a .catch on promise [duplicate]

This question already has an answer here:
Weird behavior with Promise throwing "Unhandled promise rejection" error
(1 answer)
Closed 4 years ago.
i have the following problem that i can not figure out. here is my code:
//file1.js
module.exports = {
delete: function(id) {
return new Promise((resolve,reject) => {
setTimeout(() => {reject('bla bla');}, 2000);
});
}
}
//file2.js
const file1 = require('file1');
var delPr = file1.delete(id);
delPr.then(() => {
console.log('+++++++++++++++++++++++++++');
res.status(200).json({
message : "delete post"
});});
delPr.catch((error) => {
console.log('-----------------------------');
}
when this is the code i get:
-----------------------------
(node:102437) UnhandledPromiseRejectionWarning: bla bla
(node:102437) UnhandledPromiseRejectionWarning: Unhandled promise rejection. 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(). (rejection id: 1)
(node:102437) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
when changing my code in file2.js to :
file1.delete(id).then(() => {
console.log('+++++++++++++++++++++++++++');
res.status(200).json({
message : "delete post"
});}).catch((error) => {
console.log('-----------------------------');
});
});
everything works fine and i only get the '--------' in the console, can someone please explain what is the difference?? i don't see one, and iv'e been on it for the past 3 hours.
yes .then() returns a promise and that promise is not handled.
so when you do a.then().catch() then rejection on that promise is handled by the catch

Categories

Resources