NodeJS - Cannot set Headers after they are sent to

2019-08-24 10:56发布

So I've searched around and found out that to fix the said issue, I have to return after sending a response. But my problem is, even though I have return, I still have the error.

const dbEditCourse = (req, res, db, logger) => {
    let {
        origCourse, code, description, type
    } = req.body;
    if (!code || !description || !type) {
        res.json({
            haveEmpty: true
        });
        return;
    }
    db.transaction((trx) => {
            db.select('*').from('course_strand').where('code', '=', code)
                .then(data => {
                    if (data[0]) {

                        //error happens in this block of code
                        res.json({
                            isSuccess: false
                        });
                        return;
                        //i also tried return res.json({ isSuccess: false });

                    }
                    //wrapping this in 'else' also does not work
                    return db('course_strand')
                        .returning('*')
                        .where('code', '=', origCourse)
                        .update({ code, description, type })
                })
                .then(course => {
                    return db('activity_logs')
                        .returning('*')
                        .insert({
                            date: new Date(),
                            employee_id: req.session.emp_id,
                            module: "COURSE / STRAND",
                            activity: "EDIT"
                        })
                })
                .then(activity => {
                    if (activity[0]) {
                        res.json({
                            isSuccess: true
                        });
                        return;
                    } else {
                        res.json({
                            isSuccess: false
                        });
                        return;
                    }
                })
                .then(trx.commit)
                .catch(err => {
                    logger.error(err);
                    trx.rollback;
                    res.render('pages/error-500');
                });
        })
        .catch(err => logger.error(err));
}

module.exports = {
    dbEditCourse
}

What I'm doing to produce the error is, If the record is existing, it will go into the block of code above. Aside from that specific block of code, I don't encounter the error elsewhere. And the code is working fine even though I have the error.

2条回答
做自己的国王
2楼-- · 2019-08-24 11:21
const dbEditCourse = (req, res, db, logger) => {
    let {
        origCourse, code, description, type
    } = req.body;
    if (!(code && description && type)) {
        res.json({
            haveEmpty: true
        });
        return;
    } else { // Please Try this. 
        db.transaction((trx) => {
            db.select('*').from('course_strand').where('code', '=', code)
                .then(data => {
                    if (data[0]) {

                        //error happens in this block of code
                        res.json({
                            isSuccess: false
                        });
                        return;
                        //i also tried return res.json({ isSuccess: false });

                    }
                    //wrapping this in 'else' also does not work
                    return db('course_strand')
                        .returning('*')
                        .where('code', '=', origCourse)
                        .update({ code, description, type });
                })
                .then(course => {
                    return db('activity_logs')
                        .returning('*')
                        .insert({
                            date: new Date(),
                            employee_id: req.session.emp_id,
                            module: "COURSE / STRAND",
                            activity: "EDIT"
                        });
                })
                .then(activity => {
                    if (activity[0]) {
                        res.json({
                            isSuccess: true
                        });
                        return;
                    } else {
                        res.json({
                            isSuccess: false
                        });
                        return;
                    }
                })
                .then(trx.commit)
                .catch(err => {
                    logger.error(err);
                    trx.rollback;
                    res.render('pages/error-500');
                });
        })
        .catch(err => logger.error(err));
    }

};

module.exports = {
    dbEditCourse
};

查看更多
聊天终结者
3楼-- · 2019-08-24 11:31

You cannot break a promise chain with return keyword, all .then statements will be executed (exclude you throw an error in a .then), the res.json has been called many times.

Handler all errors (include your error and system error) in catch block.

In catch block, check the error is throwing by you or not to return the response.

const dbEditCourse = (req, res, db, logger) => {
  let {
    origCourse, code, description, type
  } = req.body;
  if (!code || !description || !type) {
    res.json({
      haveEmpty: true
    });
    return;
  }

  // util throw a error
  const breakWithMyError = () => {
    throw new Error("MY_ERROR");
  }

  db.transaction((trx) => {
    db.select('*').from('course_strand').where('code', '=', code)
      .then(data => {
        if (data[0]) {

          //error happens in this block of code
          breakWithMyError();
          //i also tried return res.json({ isSuccess: false });

        }
        //wrapping this in 'else' also does not work
        return db('course_strand')
          .returning('*')
          .where('code', '=', origCourse)
          .update({ code, description, type })
      })
      .then(course => {
        return db('activity_logs')
          .returning('*')
          .insert({
            date: new Date(),
            employee_id: req.session.emp_id,
            module: "COURSE / STRAND",
            activity: "EDIT"
          })
      })
      .then(activity => {
        // revert logic, we check for error case first
        if (!activity[0]) {
          breakWithMyError();
        }
      })
      .then(trx.commit)
      .then(() => {
        // finally you can run to here without any error
        res.json({
          isSuccess: true
        });
      })
      .catch(err => {
        // If you any error, the error comes form `breakWithMyError` or any things.
        if (err.message === "MY_ERROR") {
          // the error throw by `breakWithMyError`
          return res.json({
            isSuccess: false
          });
        }
        logger.error(err);
        trx.rollback;
        // Why you return a html page in failed case? `res.status(500).json({message: "Internal server!"});`
        res.render('pages/error-500');
      });
  })
    .catch(err => logger.error(err));
}

module.exports = {
  dbEditCourse
}
查看更多
登录 后发表回答