4

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

1
  • You're not awaiting the Property.findById(id).then(…) promise. In fact you probably should use then at all here, but just const property = await Property.findById(id); … Commented Oct 1, 2017 at 10:44

1 Answer 1

5

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.sendStatus(500) // Internal server error
      case UnauthorizedError:
        return res.sendStatus(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.

Sign up to request clarification or add additional context in comments.

11 Comments

Works fine, shortest, excellent. I've confused about try/catch. Thank you very much.
When await Property.findById(id) fails, must i to use tryand catch to throw the error?
No, this will be caught by your try/catch block inside the exports.create function. Any function that throws or return Promise.reject() that gets called throughout the function call chain of the Request.create method will be caught by the try/catch block inside exports.create. To make it crystal clear, you only need that try/catch block.
@uruapanmexicansong I'm glad I could be of help! I updated my answer to show how you'd handle errors. These are thrown with throw new UnauthorizedError("Unauthorized") or return Promise.reject(new UnauthorizedError("Unauthorized")).
Wow, I came looking for copper and found gold.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.