Node.JS – Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

问题说明

在开发「你不会百度吗 API接口」时,我遇到了如标题的报错问题。

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:535:11)
    at ServerResponse.header (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:267:15)
    at exports.XMLHttpRequest.httpRequest.onreadystatechange (/Users/zihangu/Desktop/TZG API/nbhbdm/app.js:28:17)
    at exports.XMLHttpRequest.dispatchEvent (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:591:25)
    at setState (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:610:14)
    at IncomingMessage.<anonymous> (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:440:13)
    at IncomingMessage.emit (events.js:315:20)
    at IncomingMessage.Readable.read (_stream_readable.js:508:10) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
Process exited with code 1

在 stackoverflow 上查找了一下相关提问,发现此类报错通常是在尝试将多个响应发送到同一个请求时产生的。

这是我的代码。

const express = require('express');
const app = express();

app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",'3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
  });

app.get('/api/nbhbdm',function(req,res,err){
    console.log(req.query);
    var keyword = encodeURI(encodeURI(req.query.keyword));
    var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', "https://suo.im/api.htm?&key=000000000000&expireDate=2030-03-31&url=https://abcdef.cn/?s=" + keyword, true);
    httpRequest.send();
    httpRequest.onreadystatechange = function () {
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            var result = httpRequest.responseText;
            console.log(result);
            res.json({"status":"ok","slink":result,"nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
        }
        else{
            res.json({"status":"error","slink":"connection error","nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
        }
    }
})
var server = app.listen(4008, '127.0.0.1', function(){
    var host = server.address().address;
    var port = server.address().port;
    console.log("Server running at http://%s:%s", host, port);
})

onreadystatechange 的坑

由于实在是想不出我的代码有什么问题 ⬅️shab,便又去 stackoverflow 问了一下。一位好心人给我提了个醒。

顺便,你可以在这里查看我的问题。

The onreadystatechange event is triggered four times (1-4), one time for each change in the readyState.

Source: https://www.w3schools.com/js/js_ajax_http_response.asp

也就是说,这个「隐形的坑」才是问题的关键。

解决方案

在我提问时,那位好心人也帮我改好了代码。

似乎只需要 onreadystatechange 去 return 不是4的所有 readystate。

httpRequest.onreadystatechange = function () {
    if (httpRequest.readyState !== 4)
        return;
    if (httpRequest.status == 200) {
        var result = httpRequest.responseText;
        console.log(result);
        res.send("123321");
    }
    else{
        res.send("123321");
    }
}

留下评论

电子邮件地址不会被公开。 必填项已用*标注