I have a use case to resolve a Promise without returning it. Catching for errors internally, but don't want the caller to wait for the promise to resolve.
doSomething()
{
Promise.resolve()
.then(() => {
// do something.
})
.catch(reason => {
this.logger.error(reason);
});
}
Getting this error:
(node:2072) Warning: a promise was created in a handler at internal/timers.js:439:21 but was not returned from it, see http://. goo.gl/rRqMUw
at Function.Promise.cast (.../node_modules/bluebird/js/release/promise.js:225:13)
Just return something from the Promise callback where you are creating the fire and forget promise.
I'm guessing that handler is doSomething
doSomething()
{
Promise.resolve()
.then(() => {
// do something.
})
.catch(reason => {
this.logger.error(reason);
});
return null //or anything else that's sensible
}
Note: We usually ignore the error message, but sometimes they contain valuable information. In your error there's a link http://. goo.gl/rRqMUw that explains exactly this problem:d
Related
I can not understand how this thing works. can anyone explain please
`
module.exports = (thefunc) => (req,res,next)=>{
Promise.resolve(thefunc(req,res,next)).catch(next)
}
`
i searched on internet and still can not understand.
The point of this structure:
Promise.resolve(thefunc(req,res,next)).catch(next)
Is to catch any rejected promise that might be returned from calling:
thefunc(req,res,next)
And, direct the reject reason to call next(err). It is wrapped in Promise.resolve() in case thefunc(req,res,next) does not return a promise at all (perhapes even returns nothing). This makes it type-safe to add the .catch().
This attempts to add a bit of promise-awareness to your routing engine since Express, by itself, does not have promise-awareness for route handlers.
So, this will work with any of these situations inside of thefunc():
async function(req, res, next) {
if (!req.body.username) throw new Error("User Missing");
....
}
In this case, the function use here is declared as async so when it uses throw, that will cause it reject the promise that it returns. That will then end up call next(err) where err is the Error object we created there.
function(req, res, next) {
return queryMyDb(...).then(result => {
res.send(result);
});
}
In this case, if the DB query rejects, then this function will be returning a promise that rejects and the reject reason will be sent to next(err) just like in the previous example by the wrapper.
function(req, res, next) {
res.send({cntr: req.body.cntr++});
}
While this request handler doesn't cause any sort of error (assuming req.body.cntr is valid), it also doesn't return a promise. But, because the function call was wrapped in Promise.resolve(theFunc(...)) that still allows the wrapper to use the .catch() which won't actually come into play because no error occurs here, but adding the .catch() won't cause a run-time error because of the Promise.resolve() wrapper.
Note, the wrapper as shown will not catch synchronous exceptions thrown in the route handler unless the route handler is declared async (which auto-converts synchronous exceptions to a rejected promise for you).
If you want to also catch synchronous exceptions (generally advisable), you can modify it to this:
module.exports = (thefunc) => (req,res,next)=>{
try {
Promise.resolve(thefunc(req,res,next)).catch(next)
} catch(e) {
next(e);
}
}
Though, at that point, I would probably do this:
module.exports = async (thefunc) => (req,res,next)=>{
try {
await thefunc(req,res,next);
} catch(e) {
next(e);
}
}
Since it is harmless to use await on a non-promise, you don't have to wrap with Promise.resolve() when using await like this. If thefunc() happens to return a promise that rejects or happens to throw synchronously, the try/catch will catch either.
This bit of code, after connecting, does some stuff
controller.connect((response)=>{ does some stuff })
Down deep in the guts of the connect method this async function gets called, which returns a promise by way of the callback
async function ServerSend(endpoint,params,callback) {
const response = axios.get(host+endpoint, {params})
callback(response);
}
If the server is not available it correctly throws: UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:8088
What is the correct way to handle this exception? I could possibly add a catch in the async method and rewrite all the call backs to return an err. But I'd rather catch it at the caller. I have not been able to get either method to work.
axios.get(host+endpoint, {params}) // this is a promise
so if it resolves it will be ok, but if it rejects (and yuou dont have any try .. catch, any .catch attached - it will throw error that exception is unhandled.
Why way would be to:
async function ServerSend(endpoint,params,callback) {
try {
const response = await axios.get(host+endpoint, {params})
callback(null, response);
} catch (err) {
callback(err, null);
}
}
OR
function ServerSend(endpoint,params,callback) {
// most callbacks are two parameters - 1st erro or null, second data if no error is present.
axios.get(host+endpoint, {params}).then(data => callback(null, data)).catch(err => callback(err, null));
}
I'm working on a module containing a class with functions which calls an api everytimes we use a function.
I want to handle the result & catch IN the module and only send data in return.
function getAllFromTable(aTableName){
const request = {
.... aTableName
}
return apiCall(request)
}
function apiCall(requestConfig){
axios(requestConfig).then(result => {
return result.data
}
.catch(err => {
return err
}
}
That's the idea of what I would like to do but of course this only sends back "undefined"..
Is there a way to make a return in a then() to send back the data ?
Or another way to send back only the data and not a Promise to the one who calls the function "getAllFromTable()" ?
Is there a way to make a return in a then() to send back the data ? Or another way to send back only the data and not a Promise to the one who calls the function "getAllFromTable()" ?
No. In Javascript, there is NO way to return an asynchronously retrieved result directly. You HAVE to use an asynchronous mechanism such as a promise, a callback or an event to communicate back the asynchronous result. Since you already have a promise, you need to just return the promise and make sure that its resolved value is your final result. Then, the caller can use either .then() or await to get the result out of the promise.
That's the idea of what I would like to do but of course this only sends back "undefined"..
In your apiCall() function, you have to return the promise and fix your error handling.
Change this:
function apiCall(requestConfig){
axios(requestConfig).then(result => {
return result.data
}.catch(err => {
return err
});
}
to this:
function apiCall(requestConfig){
return axios(requestConfig).then(result => {
return result.data;
});
}
I removed the .catch() because you were changing the promise from rejected to resolved and making the error object be the resolved value. That is unlikely what you want for the function behavior and very unlikely what the caller wants. If you want a .catch() to log the error or something, then you can throw the error again to make sure the promise stays rejected.
function apiCall(requestConfig){
return axios(requestConfig).then(result => {
return result.data;
}).catch(err => {
// log error and rethrow so the promise stays rejected
console.log(err);
throw err;
});
}
The caller of apiCall() will then either use .then() or await to get the resolved value of the promise that the function returns.
apiCall(...).then(val => {
console.log(val);
}).catch(err => {
console.log(err);
});
I am using this chunk of code:
assert.throws(async () => {
patientSubscriber = await PatientSubscriber.create({
isSubscribed: true,
patient: patient._id,
subscriber: user._id
});
},{
message: /foo/
});
when I run it I get this:
AssertionError [ERR_ASSERTION]: Missing expected exception.
The assert API is:
https://nodejs.org/api/assert.html#assert_assert_throws_fn_error_message
Maybe I am hitting this issue?
https://github.com/nodejs/node-v0.x-archive/issues/8368
Anyone know what that error is about?
The error means that there was no exception while it was expected. async functions are syntactic sugar for promises. They never throw exceptions but may return rejected promise.
Since the assertion is expected to be synchronous, it's impossible to assert promises this way; the entire callstack should be promise-based.
As it was mentioned in comments, assert.rejects appeared in Node 10 and results in rejected promise on assertion fail.
In case promises are handled by a caller (e.g. in most testing frameworks), rejected promise needs to be returned from current function:
it('...', async () {
await assert.rejects((async () => {})()); // current function returns rejected promise
});
In case assertion promises aren't handled (e.g. in production), they result in UnhandledPromiseRejectionWarning console output, not in exceptions. unhandledRejection handler can be set to handle asynchronous errors:
process.on('unhandledRejection', err => {
console.error(err);
process.exit(1);
});
...
assert.rejects((async () => {})());
I am trying to stop a promise chain midway (After a catch). So after an error occurred in the first promise the catch will catch it but I don't want the chain to continue. I'm using bluebird. How would I do this?
getRedirectedURL(url).then(function(url) {
console.log(1);
url = domainCleanse(url);
sql = mysql.format(select, url);
return [ url, mysqlQuery(sql) ];
}).catch(function(error) {
console.log(2);
console.error(error);
socket.emit('error:unreachable', url + ' was unreachable');
}).spread(function(url, rows) {
console.log(3);
if(_.isEmpty(rows[0])) {
socketList.push({
url: url,
ttl: _.now(),
socket: socket,
added: false
});
} else {
socket.emit('done', mapResults(rows[0]));
}
}).catch(function(error) {
console.log(4);
console.error(error);
socket.emit('error', 'We could not reach ' + url + ' at this time.');
});
Generalizing your example, it looks like this:
promiseToFoo()
.then(promiseToBar)
.catch(failedToFooOrBar)
.then(promiseToFrob)
.catch(failedToFrob)
Along the happy path you are promising to Foo, then to Bar, then to Frob. Based on your description, you want to handle errors Fooing or Barring separately from errors Frobbing. So a simple solution is bury the error handling for Frob into that promise. So instead of chaining a promise to Frob, you're chaining a promise to Frob and handle errors in Frobbing. Something like this:
promiseToFoo()
.then(promiseToBar)
.catch(function (error) {
failedToFooOrBar(error);
return Promise.reject(error);
})
.then(function (x) {
return promiseToFrob(x).catch(failedToFrob);
});
A key to this is to make sure that your on-reject handler in the first catch ends up leaving the chain in a rejected state when it leaves. This is handled in the sample above by returning a rejected Promise from the handler. You can also handle it by throwing an Error from the handler. If you don't do one of these things, then the promise will be in a fulfilled state when the handler finishes and the on-fulfill handler provided by the subsequent then call will be invoked.