Search code examples
javascriptnode.jsexpressasync-awaitknex.js

Ending response when knex throws an error using async/await


I'm getting "Cannot set headers after they are sent to the client" this error in my api. I understand that I'm sending response back multiple times which causes the problem, but i'm not sure how to fix it.

The error occurs when a knex error happens in the first db call res.status(500) which returns/sends the response to the client. The problem is I'm not sure how to end the code there or should I even end it at all? I know I could probably chain my promises so this doesn't occur but I believe it would be cleaner in the end with async/await.

I'm currently forcing my code to go to the catch block in the first database call. And I know that the "Cannot set headers after they are sent to the client" errors occurs when I return/send res.sendStatus(200).

What is a good solution to this problem?

   let existingUser = await knex('user').where({ username }).orWhere({ email }) // <-- first db call
      .then(([user]) => user)
      .catch(() => res.status(500))

    if (!existingUser) {
      knex('user').insert({
        username,
        password_digest,
      }) // <-- second db call
        .then(() => res.sendStatus(200))
        .catch(() => res.sendStatus(500))
    } else {
      return () => res.sendStatus(409)
    }

Thanks in advance Stackoverflow community!


Solution

  • I would use a try-catch block rather than .then, .catch. It makes it easier to understand what the code is doing, just like async/await.

    Here is an example:

    try {
        let existingUser = await knex('user').where({ username }).orWhere({ email }).first()
    
        if (!existingUser) {
          await knex('user').insert({
            username,
            password_digest,
          })
    
          return res.sendStatus(200);
        } else {
          return res.sendStatus(409)
        }
    } catch (error) {
        return res.sendStatus(500)
    }
    

    You will jump down to the catch block if an error is thrown in the try block.

    I haven't tested this particular snippet, so please tell me if it doesn't work.