未处理的承诺拒绝警告:错误:发送标头后无法设置标头

时间:2018-09-11 20:13:34

标签: javascript node.js nock

我有以下端点,它使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块中以正确的方式处理了Promise拒绝 如果我做错了事,请纠正我。

2 个答案:

答案 0 :(得分:2)

此错误表示您已在发送响应后尝试发送响应。我认为这可以解决您的问题。

更改

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语句就可以了。

答案 1 :(得分:0)

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

问题是,您没有ssoToken,因此if块正在执行。您需要return或从next之后的if块调用res.status().json()

尝试:

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();
  }
  .....
 }