res.send之后代码执行问题

· 2 min read

express是node.js下最受欢迎的框架了,灵活的中间件思维及路由控制,使其实现了简单上手。 但是灵活往往会带来另一个问题就是可维护性,毕竟灵活对于团队开发的规范就有了更高的要求。

在实际的开发中,一些细节,需要注意,否则潜在的危险就会隐埋,并且随时可能会爆发。

如下图,构造一个API接口请求,返回结果

router.get('/c', function (req, res) {
    let conf2 = require('../conf');
    res.send({value: conf2.a});
    console.log('hello');
});

运行发现,其实res.send之后的控制台输出还是执行了,如何避免呢,加上return

router.get('/c', function (req, res) {
    let conf2 = require('../conf');
    return res.send({value: conf2.a});
    console.log('hello');
});

再次执行就没有问题了,自己看一遍官网,发现,官网给出的demo都没有写return,原因应该是官网给出的都是简单的逻辑,res.send往往是路由处理的最后一句话 那么的确写与不写是一样的,但是当我们的路由逻辑复杂一些,需要终端请求返回时,那么的确是需要return。

如下这个复杂逻辑,提前返回请求,必须写return,否则下面的逻辑仍然会继续执行,造成麻烦。

router.get('/download', function (req, res) {
  let key = req.query.key;
  let ua = parser(req.headers['user-agent']);
  redisClient.get(key, function (err, reply) {
    if (!reply) {
      return res.status(404).send('The download link has expired');
    }
    // reply is null when the key is missing
    let obj = JSON.parse(reply);
    let filePath = config.download.directory + `${obj.path}`;
    let filename = obj.filename;
    //res.download返回头部是双filename,对于Safari支持有问题,所以换流形式

    if (['Edge', 'Chrome', 'Firefox'].indexOf(ua.browser.name) > -1) {
      res.download(filePath, filename, function (err) {
          if (err) {
            logger.error('有错误');
            logger.error(err)
          }
        }
      );
    }
    else {
      let mimetype = mime.lookup(filePath);
      res.setHeader('Content-type', mimetype);
      if (ua.browser.name == 'IE') {
        res.setHeader('Content-Disposition', 'attachment; filename=' + encodeURIComponent(filename));
      } else {
        /* safari等其他非主流浏览器*/
        res.setHeader('Content-Disposition', 'attachment; filename=' + new Buffer(filename).toString('binary'));
      }
      let filestream = fs.createReadStream(filePath);
      filestream.pipe(res);
    }

  });
});