I'm using loopback 3
to build a REST service, and I want to use the async/await instead of having to use the callbacks. So instead of doing that:
MyModel.myFunction = (callback) => {
MyModel.find({where: {id: 2}}, (e, data) => {
if (e) return callback(e);
callback(null, data);
});
};
I would greatly prefer to do:
MyModel.myFunction = async (callback) => {
try {
const data = await MyModel.find({where: {id: 2}});
callback(null, data);
} catch (e) {
console.error(e);
callback(e);
}
};
The callback approach works perfectly - async/await however gives numerous errors:
UnhandledPromiseRejectionWarning: Error: Callback was already called.
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().
What's wrong? I cannot get through this issue.
I'm using loopback 3
to build a REST service, and I want to use the async/await instead of having to use the callbacks. So instead of doing that:
MyModel.myFunction = (callback) => {
MyModel.find({where: {id: 2}}, (e, data) => {
if (e) return callback(e);
callback(null, data);
});
};
I would greatly prefer to do:
MyModel.myFunction = async (callback) => {
try {
const data = await MyModel.find({where: {id: 2}});
callback(null, data);
} catch (e) {
console.error(e);
callback(e);
}
};
The callback approach works perfectly - async/await however gives numerous errors:
UnhandledPromiseRejectionWarning: Error: Callback was already called.
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().
What's wrong? I cannot get through this issue.
Share Improve this question edited May 1, 2018 at 20:21 khernik asked May 1, 2018 at 20:06 khernikkhernik 2,0912 gold badges30 silver badges55 bronze badges 5- 2 Do you really want to ignore errors (like in your original code)? – Bergi Commented May 1, 2018 at 20:12
-
2
Do not mix promises with callback style. It doesn't end up well as you can see - you are not correctly handling the case where
callback
throws. – Bergi Commented May 1, 2018 at 20:14 -
1
Is that your actual code? I copy pasted (and added a curly brace) it into a
server.js
, just tried it and it throws no errors. – user8120138 Commented May 1, 2018 at 20:18 -
Sure, I want to handle errors in the 1st case. It is the actual code, it throws errors for me, it's in the
mymodel.js
file (as the additional remote endpoint). – khernik Commented May 1, 2018 at 20:22 - if you are using async function you don't need to use callback, just return the result, just remove callback from the function arguments and instead of calling callback, just return the result. – akkonrad Commented Nov 16, 2018 at 16:29
3 Answers
Reset to default 11Some refactoring:
MyModel.myFunction = async () => {
try {
const data = await MyModel.find({where: {id: 2}});
return data; // it's enough as the async means it returns a promise
} catch (e) {
console.error(e);
throw e;
}
};
This one in case if you don't need to log an error (loopback error handler logs it instead of you):
MyModel.myFunction = async () => {
return MyModel.find({where: {id: 2}});
};
Looks like I was simply mixing two concepts, this is the solution:
MyModel.myFunction = async (callback) => {
try {
const data = await MyModel.find({where: {id: 2}});
return Promise.resolve(data);
} catch (e) {
console.error(e);
return Promise.reject(e);
}
};
An easier way would be to just use a function to resolve your promise and just pass the db query to it, like so.
async function ReturnWithResolvedPromise(dbQuery) {
try {
return Promise.resolve(dbQuery);
} catch (e) {
return Promise.reject(e);
}}
and then call this like so
let result = await ReturnWithResolvedPromise(await Users.count({where: {Region: 'UK'}}));