Unhandled Promise Rejection Warning : Error: cant set headers after they are sent

Unhandled Promise Rejection Warning : Error: cant set headers after they are sent

我有以下端点,它使 axios 请求获取用户信息。这个终点returns数据符合我的预期

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 块中以正确的方式处理承诺拒绝 如果我做错了什么,请纠正我。

此错误表示您在已发送回复后尝试发送回复。我认为这会解决您的问题。

改变

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 语句即可。

感谢您发布查询。 如果我错了,请纠正我:如果没有 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();
  }
  .....
 }