Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loopback support for async/await

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.

like image 955
khernik Avatar asked May 01 '18 20:05

khernik


People also ask

Does async await work in for loop?

When you use await , you expect JavaScript to pause execution until the awaited promise gets resolved. This means await s in a for-loop should get executed in series. The result is what you'd expect. This behaviour works with most loops (like while and for-of loops)…

What happens if you use await inside a loop?

The async-await syntax is just syntactic sugar on top of the promises API, the async tag on a function simply lets javascript know that this function would return a promise and the awaits inside the functions tell the interpreter to stay on this line of code inside this function call till the promise called on that ...

Does await in a for loop block?

No, await won't block the looping.

Does await run in parallel?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() .


2 Answers

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);
  }
};
like image 38
khernik Avatar answered Oct 06 '22 00:10

khernik


Some 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}});
};
like image 134
Maxim Sharai Avatar answered Oct 05 '22 23:10

Maxim Sharai