ChatGPT解决这个技术问题 Extra ChatGPT

错误:在将标头发送到客户端后无法设置标头

我对 Node.js 还很陌生,但遇到了一些问题。

我正在使用 Node.js 4.10 和 Express 2.4.3。

当我尝试访问 http://127.0.0.1:8888/auth/facebook 时,我将被重定向到 http://127.0.0.1:8888/auth/facebook_callback

然后我收到以下错误:

Error: Can't render headers after they are sent to the client.
    at ServerResponse.<anonymous> (http.js:573:11)
    at ServerResponse._renderHeaders (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:64:25)
    at ServerResponse.writeHead (http.js:813:20)
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:28:15
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:113:13
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/strategyExecutor.js:45:39)
    at [object Object].pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:32:3)
    at [object Object].halt (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:29:8)
    at [object Object].redirect (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:16:8)
    at [object Object].<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:77:15)
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:195:11)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
    at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
    at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
    at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
    at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
    at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
    at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9

node.js:134
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9
    at Array.<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session/memory.js:57:7)
    at EventEmitter._tickCallback (node.js:126:26)

以下是我的代码:

var fbId= "XXX";
var fbSecret= "XXXXXX";
var fbCallbackAddress= "http://127.0.0.1:8888/auth/facebook_callback"

var cookieSecret = "node";     // enter a random hash for security

var express= require('express');
var auth = require('connect-auth')
var app = express.createServer();


app.configure(function(){
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({secret: cookieSecret}));
    app.use(auth([
        auth.Facebook({
            appId : fbId,
            appSecret: fbSecret,
            callback: fbCallbackAddress,
            scope: 'offline_access,email,user_about_me,user_activities,manage_pages,publish_stream',
            failedUri: '/noauth'
        })
    ]));
    app.use(app.router);
});


app.get('/auth/facebook', function(req, res) {
  req.authenticate("facebook", function(error, authenticated) {
    if (authenticated) {
      res.redirect("/great");
      console.log("ok cool.");
      console.log(res['req']['session']);
    }
  });
});

app.get('/noauth', function(req, res) {
  console.log('Authentication Failed');
  res.send('Authentication Failed');
});

app.get('/great', function( req, res) {
  res.send('Supercoolstuff');
});

app.listen(8888);

我可以知道我的代码有什么问题吗?

visionmedia 的简单回答:github.com/visionmedia/express/issues/634
Google 向我发送了这个问题,但 ExpressJS 的较新版本具有 res.headersSent 布尔值,可用于检查设置/发送标头是否安全
对于解决此错误的其他人:如果您在路由中使用通配符,请确保将此类路由放在它们将捕获的任何其他路由之后。

4
4 revs, 3 users 88%

Express 中的 res 对象是 Node.js's http.ServerResponse (read the http.js source) 的子类。您可以随时拨打 res.setHeader(name, value),直到您拨打 res.writeHead(statusCode)。在 writeHead 之后,标头被烘焙,您只能调用 res.write(data),最后是 res.end(data)

错误“错误:发送后无法设置标头。”表示您已经处于 Body 或 Finished 状态,但某些函数试图设置 header 或 statusCode。当您看到此错误时,请尝试查找在某些正文已写入之后尝试发送标头的任何内容。例如,查找意外调用两次的回调,或在发送正文后发生的任何错误。

在您的情况下,您调用了 res.redirect(),这导致响应变为 Finished。然后您的代码抛出了一个错误(res.reqnull)。并且由于错误发生在您的实际 function(req, res, next) 中(而不是在回调中),Connect 能够捕获它,然后尝试发送 500 错误页面。但是由于标头已经发送,Node.js 的 setHeader 抛出了您看到的错误。

Node.js/Express 响应方法的完整列表以及何时必须调用它们:

响应必须在 Head 中并保持在 Head 中:

res.writeContinue() res.statusCode = 404 res.setHeader(name, value) res.getHeader(name) res.removeHeader(name) res.header(key[, val]) (Express only) res.charset = 'utf -8'(仅限 Express;仅影响 Express 特定的方法) res.contentType(type)(仅限 Express)

响应必须在 Head 中并成为 Body:

res.writeHead(statusCode, [reasonPhrase], [headers])

响应可以在 Head/Body 中并保留在 Body 中:

res.write(块,编码='utf8')

响应可以在头部/身体中并变为已完成:

res.end([数据], [编码])

响应可以是 Head/Body 并保持其当前状态:

res.addTrailers(标题)

响应必须在 Head 中并变为 Finished:

return next([err]) (Connect/Express only) 中间件函数中的任何异常(req, res, next) (Connect/Express only) res.send(body|status[, headers|status[, status]]) (仅限 Express) res.attachment(filename) (仅限 Express) res.sendfile(path[, options[, callback]]) (仅限 Express) res.json(obj[, headers|status[, status]]) (仅限 Express ) res.redirect(url[, status]) (Express only) res.cookie(name, val[, options]) (Express only) res.clearCookie(name[, options]) (Express only) res.render(view [, options[, fn]]) (Express only) res.partial(view[, options]) (Express only)


是的,检查调用 next() 或其他 cb 两次。
快速链接似乎已死
还要注意这个经典错误: res.redirect() 不会停止语句执行......所以在它之后返回。否则可能会执行其他代码,这可能会无意中导致著名的标头错误。谢谢你的解释!
在回调结束时使用 return 来避免这种情况通常是个好主意
我在中间件中犯了一个非常小的错误,我在 next() 之前没有 return,感谢这指出了错误!
L
Lance

我也遇到了这个错误一段时间。我想(希望)我已经把我的头包起来了,想把它写在这里以供参考。

当您使用 app.use 方法将中间件添加到 connectexpress(基于连接)时,您将项目附加到连接中的 Server.prototype.stack(至少对于当前的 npm install connect,它看起来很与本文中的一个 github 不同)。当服务器收到请求时,它会遍历堆栈,调用 (request, response, next) 方法。

问题是,如果在其中一个中间件项目中写入响应正文或标头(看起来可能是/或出于某种原因),但不调用 response.end() 而您调用 next() 然后随着核心 Server.prototype.handle 方法完成,它会注意到:

堆栈中没有更多项目,和/或 response.headerSent 为真。

因此,它会引发错误。但它抛出的错误只是这个基本响应(来自连接 http.js 源代码:

res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Cannot ' + req.method + ' ' + req.url);

它正在调用 res.setHeader('Content-Type', 'text/plain');,您可能已在 render 方法中设置了它,无需调用 response.end(),类似于:

response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");

一切都需要结构化的方式是这样的:

好的中间件

// middleware that does not modify the response body
var doesNotModifyBody = function(request, response, next) {
  request.params = {
    a: "b"
  };
  // calls next because it hasn't modified the header
  next();
};

// middleware that modify the response body
var doesModifyBody = function(request, response, next) {
  response.setHeader("Content-Type", "text/html");
  response.write("<p>Hello World</p>");
  response.end();
  // doesn't call next()
};

app.use(doesNotModifyBody);
app.use(doesModifyBody);

有问题的中间件

var problemMiddleware = function(request, response, next) {
  response.setHeader("Content-Type", "text/html");
  response.write("<p>Hello World</p>");
  next();
};

有问题的中间件在没有调用 response.end() 和调用 next() 的情况下设置响应标头,这会使 connect 的服务器感到困惑。


+1 这是一个很好的解释,但是当你使用 res.redirect() 的情况下呢?当中间件尝试根据某些条件进行重定向时,我经常遇到这个问题。根据您的“良好中间件”示例,中间件不应该重定向吗?
你知道我有这个确切的问题,因为你称之为有问题的中间件,但是我需要一个我返回响应但想在单独的控制器中作为链的一部分进行进一步处理的情况,我该如何去抑制这个错误?
M
Mika Sundland

此问答中的某些答案是错误的。接受的答案也不是很“实用”,所以我想发布一个用更简单的术语解释事情的答案。我的回答将涵盖我一遍又一遍看到的 99% 的错误。对于错误背后的实际原因,请查看接受的答案。

HTTP 使用一个循环,每个请求需要一个响应。当客户端发送一个请求(例如 POST 或 GET)时,服务器应该只向它发送一个响应。

此错误消息:

错误:发送后无法设置标头。

通常在您为一个请求发送多个响应时发生。确保每个请求只调用一次以下函数:

res.json()

res.send()

res.redirect()

res.render()

(还有一些很少使用的,检查接受的答案)

调用这些 res 函数时,路由回调不会返回。它将继续运行,直到它到达函数的末尾或返回语句。如果您想在发送响应时返回,您可以这样做:return res.send()

以这段代码为例:

app.post('/api/route1', function(req, res) {
  console.log('this ran');
  res.status(200).json({ message: 'ok' });
  console.log('this ran too');
  res.status(200).json({ message: 'ok' });
}

当 POST 请求发送到 /api/route1 时,它将运行回调中的每一行。将抛出 Can't set headers after they are sent 错误消息,因为 res.json() 被调用了两次,这意味着发送了两个响应。

每个请求只能发送一个响应!

上面代码示例中的错误很明显。一个更典型的问题是当您有多个分支时:

app.get('/api/company/:companyId', function(req, res) {
  const { companyId } = req.params;
  Company.findById(companyId).exec((err, company) => {
      if (err) {
        res.status(500).json(err);
      } else if (!company) {
        res.status(404).json();      // This runs.
      }
      res.status(200).json(company); // This runs as well.
    });
}

带有附加回调的这条路线在数据库中找到一家公司。查询不存在的公司时,我们将进入 else if 分支并发送 404 响应。之后,我们将继续执行下一个也发送响应的语句。现在我们已经发送了两个响应,并且会出现错误消息。我们可以通过确保只发送一个响应来修复此代码:

.exec((err, company) => {
  if (err) {
    res.status(500).json(err);
  } else if (!company) {
    res.status(404).json();         // Only this runs.
  } else {
    res.status(200).json(company);
  }
});

或者在发送响应时返回:

.exec((err, company) => {
  if (err) {
    return res.status(500).json(err);
  } else if (!company) {
    return res.status(404).json();  // Only this runs.
  }
  return res.status(200).json(company);
});

一个大罪人是异步函数。以 this 问题中的函数为例:

article.save(function(err, doc1) {
  if (err) {
    res.send(err);
  } else {
    User.findOneAndUpdate({ _id: req.user._id }, { $push: { article: doc._id } })
    .exec(function(err, doc2) {
      if (err) res.send(err);
      else     res.json(doc2);  // Will be called second.
    })

    res.json(doc1);             // Will be called first.
  }
});

这里我们在代码示例中有一个异步函数 (findOneAndUpdate())。如果没有错误 (err),将调用 findOneAndUpdate()。因为这个函数是异步的,所以 res.json(doc1) 将被立即调用。假设 findOneAndUpdate() 中没有错误。然后将调用 else 中的 res.json(doc2)。现在已经发送了两个响应,并且出现了 Can't set headers 错误消息。

在这种情况下,解决方法是删除 res.json(doc1)。要将两个文档都发送回客户端,else 中的 res.json() 可以写为 res.json({ article: doc1, user: doc2 })


您在一个异步函数中,并且必须return res.json
我的问题是在 for 循环中使用 res.send
非常感谢米卡的解释。我有 product().findById().then().then().catch()。两个 .then() 方法都有一个 res.status().json 。删除一个解决了在发送到客户端后无法设置标题的问题。
e
ergusto

我遇到了同样的问题,并意识到这是因为我在没有 return 语句的情况下调用了 res.redirect,因此随后也立即调用了 next 函数:

auth.annonymousOnly = function(req, res, next) {
    if (req.user) res.redirect('/');
    next();
};

应该是:

auth.annonymousOnly = function(req, res, next) {
    if (req.user) return res.redirect('/');
    next();
};

如果您返回,则无法进入 next()。
@corysimmons 我不明白你的意思。如果调用了重定向,则目的是不调用 next。不打算在返回后调用 next 。
只有你的答案是正确的。使用 return 而不是许多糟糕的答案我发现你的答案是正确的。
P
Peter Lyons

很多人都遇到了这个错误。这与异步处理令人困惑。很可能您的某些代码在第一个滴答声中设置标题,然后您在未来的滴答声中运行异步回调。在这期间,响应标头被发送,但随后的标头(如 30X 重定向)尝试添加额外的标头,但为时已晚,因为响应标头已经传输。

我不确定究竟是什么导致了您的错误,但将任何回调视为潜在的调查领域。

简化代码的一个简单技巧。去掉 app.configure() 并直接在您的顶级范围内调用 app.use

另请参阅 everyauth 模块,该模块执行 Facebook 和十几个其他第三方身份验证提供程序。


30X 重定向是一个 HTTP 响应代码。 w3.org/Protocols/rfc2616/rfc2616-sec10.html 代码 300-399 是重定向的不同变体,其中 302 和 301 通常用于将客户端发送到备用网址。当您在节点中执行 response.redirect(...) 时,将在响应中发送 30X 重定向标头。
哦。我在想象连续 30 个重定向或其他东西
n
nagender pratap chauhan

在 RND 之后自行发现错误:

1)我的错误代码:

return res.sendStatus(200).json({ data: result });

2)我的成功代码

return res.status(200).json({ data: result });

不同之处在于我使用了 sendStatus() 而不是 status()。


为什么你首先使用 sendStatus ?
基本上是发送前端的状态。
r
randomness

我对这个问题一头雾水,这是由于处理回调时的粗心错误而发生的。未返回的回调会导致响应被设置两次。!

我的程序有一个验证请求和查询数据库的代码。验证是否存在错误后,我用验证错误回调 index.js 。如果验证通过,它将继续并以成功/失败命中数据库。

    var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
   else
    some code 
    callback(null, success);

发生的事情是:万一验证失败,回调被调用并响应被设置。但没有归还。所以它仍然继续该方法转到 db 并点击 success/failure 。它再次调用相同的回调,导致现在设置两次响应。

所以解决方案很简单,一旦发生错误,您需要“返回”回调,以便该方法不会继续执行,因此设置一次响应对象

  var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
        return;
    else
       some code 
       callback(null, success);

谢谢!原来这也是我的问题。只是做了一个 ctrl+f 并发现 callback(...) 后面没有 return; 最终导致 res.send(...) 被调用两次。
d
dKen

当您在发送响应后传递语句时,您会遇到这种类型的错误。

例如:

res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");

将导致您看到的错误,因为一旦发送响应,将不会执行以下 res.send

如果你想做任何事情,你应该在发送响应之前做。


B
Badr Bellaj

当您发送 2 个响应时会发生此错误。例如 :

if(condition A)
{ 

      res.render('Profile', {client:client_});

}

if (condition B){

      res.render('Profile', {client:client_});
    }
  }

想象一下,如果由于某种原因条件 A 和 B 为真,那么在第二个 render 中,您将收到该错误


S
Surendra Parchuru

有时,当您尝试在 res.end 或 res.send 之后调用 next() 函数时,您可能会收到此错误,如果您在函数中 res.send 或 res.end 之后有 next() ,请尝试删除。注意:这里的 next() 表示在用您的响应(即 res.send 或 res.end)响应客户端之后,您仍在尝试执行一些代码以再次响应,因此这是不合法的。

例子 :

router.get('/',function (req,res,next){
     res.send("request received");
     next(); // this will give you the above exception 
});

从上面的函数中删除 next() ,它将起作用。


事实上,这就是我的情况,中间件中挥之不去的 next() 调用导致了这个问题。我花了将近一个小时才意识到……
这真太了不起了。我的中间件中有一个额外的 next() ,它给出了错误。谢谢哥们
K
Krishnadas PC

如果您使用回调函数,请在 err 块之后使用 return。这是可能发生此错误的场景之一。

userModel.createUser(data, function(err, data) {
    if(err) {
      res.status = 422
      res.json(err)
      return // without this return the error can happen.
    }
    return res.json(data)
  })

在节点版本 v10.16.0 和 express 4.16.4 上测试


S
Sudharshann D

我只需添加 return 关键字,例如:return res.redirect("/great");,它就起作用了!


M
Mohammed Ramadan

还有其他原因导致此错误,并且是当您没有在 res.send、res.json 等前面添加 return 关键字时......


哇。这就是原因
b
blented

在我的情况下,导致问题的是 304 响应(缓存)。

最简单的解决方案:

app.disable('etag');

如果您想要更多控制权,请在此处替代解决方案:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/


就我而言,也是 304 响应。我正在使用纤维进行处理。无论如何,您的回答都会有很大帮助。谢谢你
谁能解释删除 etag 标头的含义是什么?
ETags 允许服务器不发送未更改的内容。关闭它会禁用此功能。 ETag 维基百科条目 (en.wikipedia.org/wiki/HTTP_ETag) 有更长的解释。
M
Mike

对于任何人来说,其他解决方案都没有帮助,在我的情况下,这体现在处理图像上传但没有处理超时的路由上,因此如果上传时间过长并且超时,当回调被触发时发送超时响应后,调用 res.send() 会导致崩溃,因为标头已设置为考虑超时。

这很容易通过设置一个非常短的超时并用相当大的图像击中路线来重现,每次都会重现崩溃。


您如何处理超时以避免这种情况?
Z
Zoltán

在我的情况下,当我没有在我的 React 组件的 componentWillUnmount 回调中取消订阅频道时,React 和 postal.js 就会发生这种情况。


s
shriek

请检查您的代码是否为单个请求返回多个 res.send() 语句。就像我遇到这个问题时一样......

我在我的 restify 节点应用程序中遇到了这个问题。错误在于

switch (status) {
    case -1:
      res.send(400);
    case 0:
      res.send(200);
    default:
      res.send(500);
}

我在不写中断的情况下使用 switch 处理各种情况。对switch case不太熟悉的人都知道,不用break,return关键字。 case 下的代码和它的下一行无论如何都会被执行。所以即使我想发送单个 res.send,由于这个错误它返回了多个 res.send 语句,这提示

错误:发送到客户端后无法设置标头。

通过在每个 res.send() 方法(如 return res.send(200)

switch (status) {
    case -1:
      res.send(400);
      break;
    case 0:
      res.send(200);
      break;
    default:
      res.send(500);
      break;
}

A
Adam Boostani

就靠这个了。您可以通过此函数传递响应:

app.use(function(req,res,next){
  var _send = res.send;
  var sent = false;
  res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
  next();
});

A
Ankit Manchanda

当响应被传递给客户端并且您再次尝试给出响应时,就会发生这种情况。您必须检查您的代码是否在某处再次向客户端返回响应,这会导致此错误。当您想返回时,检查并返回响应一次。


F
Farbod Aprin

请在您的 app.get 中搜索 res.send("your result"); 之前是否未设置状态

我刚刚删除:

res.sendStatus(200);

并且响应在那之后起作用!

res.send("your result");

g
genericUser

较新版本的 Node 支持 res.headersSent 布尔表达式。您可以使用它来验证您是否已经发送了响应:

if (!res.headersSent) // if doesn't sent yet
    res.status(200).send({ "message": "This is a message" })

笔记!虽然这有效并回答了问题,但这不是解决问题的正确方法,不推荐!

多次发送响应表明您的代码中有问题需要修复(这与在您的函数中一个接一个地使用两个返回语句相同。这是一个错误)。


不要这样做。如果您收到此错误,则您有一个发送两次响应的代码路径。改为修复代码路径。
非常同意@nicholaswmin!我会将您的注释添加到我的答案中:)
A
ASHISH R

添加这个中间件,它会工作

app.use(function(req,res,next){
 var _send = res.send;
var sent = false;
res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
next();
});

S
Sanjay

如果您没有从上面得到帮助:对于新手这个错误背后的原因是多次发送请求,让我们从某些情况下理解:- 1.`

module.exports = (req,res,next)=>{
        try{
           const decoded  = jwt.verify(req.body.token,"secret");
           req.userData = decoded;
           next();
        }catch(error){
            return res.status(401).json({message:'Auth failed'});
        }
        next();   
        }

` 在上面调用 next() 两次会引发错误

router.delete('/:orderId', (req, res, next) => { Order.remove({_id:req.params.orderId},(err,data)=>{ if(err){ **res .status(500).json(err);** }else{ res.status(200).json(data); } *res.status(200).json(data);* }) })

这里响应是发送两次检查您是否已经发送了响应


N
Naved Ahmad

这很可能更像是一个节点的事情,99% 的时间它是一个双重回调导致你响应两次,或者 next()ing 两次等等,该死的肯定。它解决了我在循环中使用 next() 的问题。从循环中删除 next() 或停止多次调用它。


我遇到了同样的错误,这是因为在同一个中间件函数中我调用了两个函数,每个函数都调用了 next()。我通过创建第二个中间件函数并将其中一个函数移入其中来修复错误,因此每个中间件函数中只有一个 next() 调用。这是解决问题的提交:github.com/DataHighway-DHX/faucet/commit/…
E
Engin Karataş

如果您在一次 api 调用中使用了两个 res.end() 函数,则会显示此错误

例如

  app.post("/auth", function (request, res) {
    var username = request.body.username;
    var password = request.body.password;
    if (username && password) {
      let sql =
        "SELECT username, worker_name, worker_surname, id FROM workers where username = ? AND password=?";
      con.query(sql, [username, password], function (error, results, fields) {
        if (results.length > 0) {
          res.status(200).send(results);
          res.end();
  
        }
        res.status(404).send("Incorrect Username and/or Password!");
      });
    } else {
      res.send("Please enter Username and Password!");
    }
    res.end();

  });

M
Marvin

问题出在 /auth/facebook 路由中,以便于理解,一旦您已经从客户端发送了响应,则不得为下一个后继块设置以下任何其他功能,这也与 JavaScript 的同步有关,

为了深入理解,它看起来像这段代码;

async function getRequest(){
   let data = await API.get();
   return data;
   let json = data.json(); // will not read this line
}

在您的情况下,console.log("ok cool.");console.log(res['req']['session']) 必须放在 res.redirect("/great") 之前

https://i.stack.imgur.com/tik61.png

希望它有意义,欢迎:)


t
trustidkid

当我尝试在循环函数中发送响应时,我遇到了类似的错误。简单的解决方案是移动

res.send('发送回复');

退出循环,因为您只能发送一次响应标头。

https://www.tutorialspoint.com/nodejs/nodejs_response_object.htm


R
Rupak

检查你的代码。对我来说,我在同一个 if 语句中使用了 res.status 两次。第一个设置标题状态,第二个尝试更改它,这导致了问题。


谢啦。但是 res.end() 和 res.send() 有什么区别,我认为两者都会终止 api 调用。 res.send() 发送响应并停止函数,而 res.end() 仅终止函数而不发送响应。真的吗?
J
Janac Meena

在 Typescript 中,我的问题是收到消息后我没有关闭 websocket 连接。

WebSocket.on("message", (data) => {
    receivedMessage = true;
    doSomething(data);
    localSocket.close(); //This close the connection, allowing 
});

r
rharding

我在嵌套 Promise 时遇到了这个问题。 Promise 中的 Promise 会返回 200 给服务器,但是外部 Promise 的 catch 语句会返回 500。一旦我解决了这个问题,问题就消失了。


你到底是怎么解决这个问题的?我对承诺有同样的问题。我无法避免嵌套它们......那么我如何在 return 语句处停止执行?

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅