【问题标题】:Unhandled Promise Rejection Warning : Error: cant set headers after they are sent未处理的承诺拒绝警告:错误:发送后无法设置标头
【发布时间】:2018-09-11 20:13:33
【问题描述】:

我有以下端点,它使 axios 请求获取用户信息。这个端点按我的预期返回数据。

const axios = require('axios');
const router = require('express').Router();
const config = require('../config');
const constants = require('../constants');
const errors = require('../utils/errors');
const ssoTokenService = require('../utils/sso-token-util'); // takes auth token from req header or cookie

router.get('/', (req, res) => {
  const ssoToken = ssoTokenService.getSsoToken(req);
  if (!ssoToken) {
    res.status(constants.HTTP_UNAUTHORIZED).json({
      errors: [{
        code: 401,
        message: 'sso token is missing in header',
      }],
      message: 'UnAuthorized'
    });
  }
  const httpFetchUserInfo = {
    headers: Object.assign(res._headers, {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      'x-correlation-id': res.locals.xCorrelationID,
      MYSAPSSO2: ssoToken,
    }),
    method: 'GET',
    url: `${config.app.entSapUserUrl}/sapusers`,
    timeout: config.app.enterpriseHTTPTimeout
  };
  axios(httpFetchUserInfo)
    .then((entFetchUserInfoAPIResponse) => {

      res.status(200).json(entFetchUserInfoAPIResponse.data);

    }).catch((err) => {
      let errorList;
      if (err && err.response && err.response.data && err.response.data.errorList) {
        errorList = err.response.data.errorList;
      }
      const error = errors.createEntError(err.message, errorList);
      if (err.response && err.response.status) {
        res.status(err.response.status).json(error);
      } else {
        res.status(constants.HTTP_SERVER_ERROR).json(error);
      }
    });

});
module.exports = router;

但我对此端点有以下单元测试

it('verify returns bad request if query is not specified', (done) => {
  interceptor = nock(config.app.entSapUserUrl)
    .get('/sapusers')
    .reply(constants.HTTP_OK, {
      userId: 'ABC456',
      customerId: '',
      firstName: 'ABC',
      lastName: 'KKK',
      branchId: ''
    });

  request(app)
    .get('/user')
    .set({
      'Content-Type': 'application/json',
      MYSAPSSO2: 'hjikgvkjvlhguiohgjklnhguio'
    })
    .expect(constants.HTTP_OK, {
      userId: 'ABC456',
      customerId: '',
      firstName: 'ABC',
      lastName: 'KKK',
      branchId: ''
    })
    .end((err) => {
      if (err) {
        return done(err);
      }
      done();
    });
});

it('verify whether sso token is necessary', (done) => {
  request(app)
    .get('/user')
    .set({
      'Content-Type': 'application/json',
    })
    .expect(constants.HTTP_UNAUTHORIZED,

      {
        errors: [{
          code: 401,
          message: 'sso token is missing in header',
        }],
        message: 'UnAuthorized'
      }

    )
    .end((err) => {
      if (err) {
        return done(err);
      }
      done();
    });
});

如果我运行测试,所有测试都通过但在控制台中我可以看到以下错误消息

✓ verify returns bad request if query is not specified

(node: 41573) UnhandledPromiseRejectionWarning: Error: Can 't set headers after they are sent.
at validateHeader(_http_outgoing.js: 491: 11)
at ServerResponse.setHeader(_http_outgoing.js: 498: 3)
at ServerResponse.header(/Users/c
  42470 / localApp / node_modules / express / lib / response.js: 767: 10)
at ServerResponse.send(/Users/c
  42470 / localApp / node_modules / express / lib / response.js: 170: 12)
at ServerResponse.json(/Users/c
  42470 / localApp / node_modules / express / lib / response.js: 267: 15)
at axios.then.catch.err(/Users/c
  42470 / localApp / server / routes / user.js: 2: 937)
at < anonymous >
  at process._tickCallback(internal / process / next_tick.js: 188: 7)
  (node: 41573) UnhandledPromiseRejectionWarning: Unhandled promise rejection.This error originated either by throwing inside of an async function without a
catch block, or by rejecting a promise which was not handled with.catch().(rejection id: 54)

我假设我在 catch 块中以正确的方式处理承诺拒绝 如果我做错了什么,请纠正我。

【问题讨论】:

    标签: javascript node.js nock


    【解决方案1】:

    此错误表示您在发送响应后尝试发送响应。我想这会解决你的问题。

    改变

    if (!ssoToken) {
        res.status(constants.HTTP_UNAUTHORIZED).json({
          errors: [{
            code: 401,
            message: 'sso token is missing in header',
          }],
          message: 'UnAuthorized'
        });
      }
    

    if (!ssoToken) {
        return res.status(constants.HTTP_UNAUTHORIZED).json({
          errors: [{
            code: 401,
            message: 'sso token is missing in header',
          }],
          message: 'UnAuthorized'
        });
      }
    

    我认为您只需要添加 return 语句就可以了。

    【讨论】:

    • 谢谢艾萨克。像魅力一样工作:)
    • 谢谢,非常感谢 :)
    【解决方案2】:

    感谢您发布您的查询。 如果我错了,请纠正我:如果没有 ssoToken,那么您想要为 unauthorized 发送 JSON 响应,否则您想要获取数据。

    问题是,你没有ssoToken,所以if 块正在被执行。您需要return 或在res.status().json() 之后的if 块中调用next

    试试:

    router.get('/', (req, res, next) => {
      const ssoToken = ssoTokenService.getSsoToken(req);
      if (!ssoToken) {
        res.status(constants.HTTP_UNAUTHORIZED).json({
          errors: [{
            code: 401,
            message: 'sso token is missing in header',
          }],
          message: 'UnAuthorized'
        }).next();
      }
      .....
     }

    【讨论】:

      猜你喜欢
      • 2018-01-04
      • 2017-09-08
      • 1970-01-01
      • 2017-12-20
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 2021-06-03
      • 2016-09-02
      相关资源
      最近更新 更多