You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const rp=require('request-promise');
rp(...).then(...).catch(...).finally(function () {
// This is called after the request finishes either successful or not successful.
return res.send(_objResult);//这句偶尔会报错
});
上面那段是一个公共方法,我封装成了一个ApiCall,大部分都会走这个函数,有没可能是并发导致一个请求还未发送出去另一个请求又进来了?请大神帮忙看下~
QQ 617284237
1
1
1
1
1
1
1
1
1
1
1
有多次调用res.send之类的方法就会出现这种
@zengming00 那意思是报错的这个地方之前还调用了一次send之类的方法么。但是并没有额
@xulayen 仔细查查,肯定有,或者不是在之前而是在之后
JSBINhttps://jsbin.com/xunututehi/edit?js
return res.redirect(_forword); //这句话 偶尔报错,但是之前之后也没有 res.send之类的操作
你的catch里面有没有返回呢? 如果有错误了,最后还会走finally
图上是源码 705行。
这个,在生产环境下有时候也会出现 这个错
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:771:10)
at ServerResponse.append (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:732:15)
at ServerResponse.res.cookie (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:857:8)
at Request.cookie [as _callback] (/mnt/www/pgyer/nodejs-middle/server/api/admin/account/index.js:705:17)
at Request.self.callback (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:185:22)
at Request.emit (events.js:198:13)
at Request.<anonymous> (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:1161:10)
at Request.emit (events.js:198:13)
at IncomingMessage.<anonymous> (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:286:20)
at IncomingMessage.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1129:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
请确保这些设置在 send之前 只要发送 send执行过一次,再涉及到 set cookie、set header这种设置 http head 部分的都会报错
send只能发送一次吧,write可以多次
@zhhb 是在send之前,现在又出现了一次
这句话之前没有任何 set cookie、set header 的操作了
@zhhb 这里用了一个异步promise ,报错好像是报这个promie有问题。
router.get('/:customerid/:accode/:timestamp/:sign', async function (req, res, next) {
var reply = await client.get(`${key}`);
...
return res.redirect(reply);
...
});
下面是promise功能代码,看下是哪里没有捕获promise异常?
const config = require('../../config/index');
var redis = require("redis"),
client = redis.createClient(config.redis);
client.on("error", function (err) {
console.log("Error " + err);
});
client.on('ready', function (res) {
console.log('redis is ready,Go!');
});
function clientCache() { }
let text = async (key) => {
let doc = await new Promise((resolve) => {
// setTimeout(() => {
// Promise.reject(new Error('unhandledrejection'))
// }, 0);
client.get(key, function (err, res) {
return resolve(res);
});
}).catch((e) => {
console.log(e)
});
return JSON.parse(doc);
};
clientCache.set = function (key, value) {
value = JSON.stringify(value);
return client.set(key, value, function (err) {
if (err) {
console.error(err);
}
});
};
clientCache.get = async (key) => {
return await text(key);
};
clientCache.expire = function (key, time) {
return client.expire(key, time);
};
module.exports = exports = clientCache;
@shadow88sky @zengming00 @zhhb @ounana 大神们,帮我看看什么问题么
你看一下请求的返回头是不是开启了keep-alive。因为node服务端keepalive的超时默认是5000毫秒,要不把服务端默认时间改大,要不把客户端keepalive时间改小。否则客户端超时大于服务端,服务端TCP关了,但是客户端还以为这个TCP还在,准备复用也会报这个错。
@zy445566 没有开启呢
@zy445566 报错信息:
/mnt/www/pgyer/nodejs-middle/server/api/frontEnd/forword/index.js:163:40 代码就是下面的 return res.redirect(_forword);
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:771:10) at ServerResponse.location (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:888:15)
at ServerResponse.redirect (/mnt/www/pgyer/nodejs-middle/node_modules/express/lib/response.js:926:18)
at Request.redirect [as _callback] (/mnt/www/pgyer/nodejs-middle/server/api/frontEnd/forword/index.js:163:40)
at Request.self.callback (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:185:22)
at Request.emit (events.js:198:13) at Request. (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:1161:10)
at Request.emit (events.js:198:13) at IncomingMessage. (/mnt/www/pgyer/nodejs-middle/node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:286:20) at IncomingMessage.emit (events.js:203:15) at endReadableNT (_stream_readable.js:1129:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
源码:
这是/redis/index.js
const config = require('../../config/index');
var redis = require("redis"),
client = redis.createClient({
...config.redis
});
client.on("error", function (err) {
console.error("Errorssss " + JSON.stringify(err));
});
client.on('ready', function (res) {
console.log('redis is ready,Go!');
});
function clientCache() { }
let text = async (key) => {
let doc = await new Promise((resolve, reject) => {
client.get(key, function (err, res) {
if (err) {
console.log(err);
reject(err);
return;
}
return resolve(res);
});
}).catch((e) => {
debugger;
console.error(e);
});
return doc ? JSON.parse(doc) : null;
};
clientCache.set = function (key, value) {
value = JSON.stringify(value);
return client.set(key, value, function (err) {
if (err) {
console.error(err);
client = redis.createClient({
...config.redis
});
return clientCache.set(key, value);
}
});
};
clientCache.get = async (key) => {
// client = redis.createClient({
// ...config.redis
// });
return await text(key);
};
clientCache.expire = function (key, time) {
return client.expire(key, time);
};
module.exports = exports = clientCache;
这是/forword/index.js
const Express = require('express');
const router = Express.Router();
// const codeState = require('../../../config/codeState');
// const result = require('../../../config/index').result;
// const token = require('../../../common/token');
const {
config,
SelfCookie,
codeState,
result,
log,
token,
HttpApi,
Client,
DEBUGGER,
ResultFactory
} = require('../../../namespaceMain');
const request = require('request');
const md5 = require('md5');
const client = require("../../../common/redis");
/**
* @api {get} /forword/[customerid]/[accode]/[timestamp]/[sign] 前端分流管理✔
* @apiDescription 前端主入口
* @apiVersion 1.0.0
* @apiSuccessExample {json}
* Success-Response:
* 跳转至前端活动页面……
*
* @apiErrorExample {json}
* Error-Response:
* 跳转至前端Error页面……
*
* @apiGroup FrontEnd
* @apiParam {string} customerid 客户编号
* @apiParam {string} accode 数码
* @apiParam {string} timestamp 时间戳
* @apiParam {string} sign 签名,加密方式`md5(customerid+accode+token+timestamp)`;token为约定的值
*/
router.get('/:customerid/:accode/:timestamp/:sign', async function (req, res, next) {
try {
debugger;
const _result = '网络出了个小差……';
console.log(`/:customerid/:accode/:timestamp/:sign ${JSON.stringify(req.params)}`);
var _customerid = req.params.customerid,
_accode = req.params.accode,
__header_sign = req.params.sign,
__timestamp = req.params.timestamp,
__sign = md5(_customerid + _accode + config.ZhshToNodejsToken[_customerid] + __timestamp),
_param_notnull = (_customerid && _accode && __header_sign),
_b_tokenisok = (__sign === __header_sign),
_code_sign = `${_customerid}_${_accode}_${__timestamp}_${__sign}`;
log.logger.info(`/:customerid/:accode/:timestamp/:sign /${_customerid}/${_code_sign}/${__timestamp}/${__sign} SessionId: ${req.session.id} GetParameter: \n `);
console.log(`/forword/index - /${_customerid}/${_code_sign}/${__timestamp}/${__sign} SessionId: ${req.session.id}`);
if (!config.EnableZhshToNodejsToken) {
_param_notnull = (_customerid && _accode);
_b_tokenisok = true;
}
const key = `forword:${_customerid}:${_accode}`;
const key_info = `forword:${_customerid}:actinfo:${_code_sign}`;
if (!_param_notnull) {
log.logger.info('/forword/index 参数为空或值错误' + "\n");
console.log('/forword/index 参数为空或值错误' + "\n");
return res.send(_result);
}
if (!_b_tokenisok) {
log.logger.info('/forword/index 签名校验不成功' + "\n");
console.log('/forword/index 签名校验不成功' + "\n");
return res.send(_result);
}
console.time('/forword/index');
var reply = await client.get(`${key}`);
if (reply) {
console.log(`/forword/index - 已缓存 ${JSON.stringify(reply)}`);
console.timeEnd('/forword/index');
return res.redirect(reply);
} else {
var _f = {
customerid: _customerid,
accode: _code_sign
}
log.logger.info('/forword/index SessionId:' + req.session.id + ' Begin:', JSON.stringify(_f) + "\n");
request({
url: HttpApi.Home.Index,
method: "POST",
json: true,
headers: {
"content-type": "application/json",
"Authorization": req.session.Authorization
},
form: _f
}, function (error, response, body) {
//log.logger.info(JSON.parse(body)+ "\n");
var str_body = JSON.stringify(body);
log.logger.info('/forword/index SessionId:' + req.session.id + ' End:', str_body + "\n");
console.timeEnd('/forword/index');
console.log(`/forword/index - Response:${str_body}`);
if (body.success) {
if (body.result && body.result.module && body.result.module.template && body.result.module.template.url && body.result.module.id) {
var _type = body.result.module.template.url;
var _moduleid = body.result.module.id;
var _forword = `${config.FrontendToDomain}${_type}${_customerid}/${_moduleid}/${_code_sign}`;
client.set(`${key}`, _forword, 'EX', (60 * 1 * 30));//30 分钟失效
client.set(`${key_info}`, str_body, 'EX', (60 * 1 * 30));//30 分钟失效
return res.redirect(_forword);//这句话报错
} else {
log.logger.info('/forword/index 模块未配置成功!' + "\n");
console.log('/forword/index 模块未配置成功!' + "\n");
return res.send(_result);
}
} else {
log.logger.info('/forword/index 返回 false' + "\n");
console.log('/forword/index 返回 false' + "\n");
return res.send(_result);
}
});
}
} catch (e) {
console.error('00000000000000000000000000000000');
console.error(JSON.stringify(e));
}
});
module.exports = router;
你是不是后面还有啥中间建执行了?
@heguangda 后面没有中间件执行,前面有中间件