uruapanmexicansong uruapanmexicansong - 3 years ago 217
Javascript Question

Async function always return undefined

im using nodejs 8. I've replaced promise structure code to use async and await.

I have an issue when I need to return an object but await sentence resolve undefined.

This is my controller method:

request.create = async (id, params) => {
try {
let request = await new Request(Object.assign(params, { property : id })).save()
if ('_id' in request) {
Property.findById(id).then( async (property) => {
property.requests.push(request._id)
await property.save()

let response = {
status: 200,
message: lang.__('general.success.created','Request')
}

return Promise.resolve(response)
})
}
}
catch (err) {
let response = {
status: 400,
message: lang.__('general.error.fatalError')
}

return Promise.reject(response)
}
}


In http request function:

exports.create = async (req, res) => {
try {
let response = await Request.create(req.params.id, req.body)
console.log(response)
res.send(response)
}

catch (err) {
res.status(err.status).send(err)
}
}


I tried returning
Promise.resolve(response)
and
Promise.reject(response)
with
then
and
catch
in the middleware function and is occurring the same.

What's wrong?

Thanks a lot, cheers

Answer Source

You don't necessarily need to interact with the promises at all inside an async function. Inside an async function, the regular throw syntax is the same as return Promise.reject() because an async function always returns a Promise. Another thing I noticed with your code is that you're rejecting promises inside a HTTP handler, which will definitely lead to unexpected behavior later on. You should instead handle all errors directly in the handler and act on them accordingly, instead of returning/throwing them.

Your code could be rewritten like so:

request.create = async (id, params) => {
  let request = await new Request(Object.assign(params, { property : id })).save()
  if ('_id' in request) {
    let property = await Property.findById(id)
    property.requests.push(request._id)
    await property.save()
  }
}

And your http handler:

exports.create = async (req, res) => {
  try {
    await Request.create(req.params.id, req.body)
    res.send({
      status: 200,
      message: lang.__('general.success.created','Request')
    })
  } catch (err) {
    switch (err.constructor) {
      case DatabaseConnectionError: // Not connected to database
        return res.status(500) // Internal server error
      case UnauthorizedError:
        return res.status(401) // Unauthorized
      case default:
        return res.status(400).send(err) // Generic error
    }
  }
}

Error classes:

class DatabaseConnectionError extends Error {}
class UnauthorizedError extends Error {}

Because you have that try/catch block inside your http handler method, anything that throws or rejects inside the Request.create method will be caught there. See https://repl.it/LtLo/3 for a more concise example of how errors thrown from async function or Promises doesn't need to be caught directly where they are first called from.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download