त्रुटि: क्लाइंट को भेजे जाने के बाद हेडर सेट नहीं कर सकते


724

मैं Node.js के लिए काफी नया हूं और मुझे कुछ समस्याएं हैं।

मैं Node.js 4.10 और एक्सप्रेस 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);

क्या मुझे पता है कि मेरे कोड में क्या गलत है?


दूरदर्शन से सरल उत्तर: github.com/visionmedia/express/issues/634
shi11i

2
Google ने मुझे इस प्रश्न पर भेजा है, लेकिन ExpressJS के नए संस्करणों में res.headersSent बूलियन है, जिसका उपयोग यह जांचने के लिए किया जा सकता है कि हेडर सेट करने / भेजने के लिए सुरक्षित है
जूलियन सोरो

जवाबों:


1112

resएक्सप्रेस में वस्तु का एक उपवर्ग है Node.js केhttp.ServerResponse ( http.js स्रोत पढ़ा )। res.setHeader(name, value)जब तक आप कॉल करते हैं, तब तक आपको जितनी बार चाहें कॉल करने की अनुमति है res.writeHead(statusCode)। के बाद writeHead, हेडर बेक किए जाते हैं और आप केवल कॉल कर सकते हैं res.write(data), और अंत में res.end(data)

त्रुटि "त्रुटि: भेजे जाने के बाद हेडर सेट नहीं कर सकते।" इसका मतलब है कि आप पहले से ही बॉडी या समाप्त स्थिति में हैं, लेकिन कुछ फ़ंक्शन ने हेडर या स्टेटसकोड सेट करने का प्रयास किया है। जब आप इस त्रुटि को देखते हैं, तो कुछ भी देखने की कोशिश करें जो कि शरीर के कुछ पहले ही लिखे जाने के बाद हेडर भेजने की कोशिश करता है। उदाहरण के लिए, कॉलबैक की तलाश करें, जिसे गलती से दो बार कहा जाता है, या कोई त्रुटि जो शरीर भेजे जाने के बाद होती है।

आपके मामले में, आपने कॉल किया res.redirect(), जिसके कारण प्रतिक्रिया समाप्त हो गई। तब आपके कोड ने एक त्रुटि ( res.reqहै null) फेंक दी । और चूंकि त्रुटि आपके वास्तविक function(req, res, next)(कॉलबैक के भीतर नहीं) के भीतर हुई थी, कनेक्ट इसे पकड़ने में सक्षम था और फिर 500 त्रुटि पृष्ठ भेजने की कोशिश की। लेकिन जब से हेडर पहले ही भेजे गए थे, Node.js setHeaderने आपके द्वारा देखी गई त्रुटि को फेंक दिया।

Node.js / एक्सप्रेस प्रतिक्रिया विधियों की व्यापक सूची और जब उन्हें बुलाया जाना चाहिए:

जवाब में होना चाहिए सिर और में रहता है सिर :

  1. res.writeContinue()
  2. res.statusCode = 404
  3. res.setHeader(name, value)
  4. res.getHeader(name)
  5. res.removeHeader(name)
  6. res.header(key[, val]) (केवल एक्सप्रेस)
  7. res.charset = 'utf-8' (केवल एक्सप्रेस, केवल एक्सप्रेस-विशिष्ट विधियों को प्रभावित करता है)
  8. res.contentType(type) (केवल एक्सप्रेस)

प्रतिक्रिया सिर में होनी चाहिए और शरीर बन जाएगी :

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

प्रतिक्रिया हेड / बॉडी में हो सकती है और बॉडी में बनी रहती है :

  1. res.write(chunk, encoding='utf8')

प्रतिक्रिया सिर / शरीर में हो सकती है और समाप्त हो सकती है :

  1. res.end([data], [encoding])

प्रतिक्रिया सिर / शरीर में हो सकती है और अपनी वर्तमान स्थिति में बनी रहती है:

  1. res.addTrailers(headers)

प्रतिक्रिया हेड में होनी चाहिए और समाप्त हो जाएगी :

  1. return next([err]) (कनेक्ट / एक्सप्रेस केवल)
  2. मिडलवेयर के भीतर कोई अपवाद function(req, res, next)(कनेक्ट / एक्सप्रेस केवल)
  3. res.send(body|status[, headers|status[, status]]) (केवल एक्सप्रेस)
  4. res.attachment(filename) (केवल एक्सप्रेस)
  5. res.sendfile(path[, options[, callback]]) (केवल एक्सप्रेस)
  6. res.json(obj[, headers|status[, status]]) (केवल एक्सप्रेस)
  7. res.redirect(url[, status]) (केवल एक्सप्रेस)
  8. res.cookie(name, val[, options]) (केवल एक्सप्रेस)
  9. res.clearCookie(name[, options]) (केवल एक्सप्रेस)
  10. res.render(view[, options[, fn]]) (केवल एक्सप्रेस)
  11. res.partial(view[, options]) (केवल एक्सप्रेस)

13
हां, दो बार () या अन्य सीबी को कॉल करने के लिए जांचें।
टोनी गुटिरेज

3
एक्सप्रेस लिंक मृत लगता है
कोरहान ओज़टर्क

25
इस क्लासिक गलती को भी देखें: res.redirect () स्टेटमेंट एक्जीक्यूशन को नहीं रोकता है ... इसलिए इसके बाद वापस लौटें। अन्यथा अन्य कोड को निष्पादित किया जा सकता है जो अनजाने में प्रसिद्ध हेडर त्रुटि का कारण बन सकता है। स्पष्टीकरण के लिए Thanx!
केलुजन

इससे बचने के लिए अपने कॉलबैक के अंत में रिटर्न का उपयोग करने के लिए इसका एक अच्छा विचार है
ठाकुरी

4
मैंने अपने मिडलवेयर में बहुत छोटी त्रुटि की, मैंने returnपहले नहीं किया next(), धन्यवाद, इसने मुझे त्रुटि की ओर इशारा किया!
इलक्रक्स

113

मैं थोड़ी देर के लिए इस त्रुटि में भाग गया। मुझे लगता है कि (आशा) मैंने अपना सिर इसके चारों ओर लपेट लिया है, इसे संदर्भ के लिए यहां लिखना चाहता हूं।

जब आप विधि का उपयोग करने के लिए कनेक्ट या एक्सप्रेस (जो कनेक्ट पर बनाया गया है) के लिए मिडिलवेयर जोड़ते हैं app.use, तो आप Server.prototype.stackकनेक्ट करने के लिए आइटम जोड़ रहे हैं (कम से कम वर्तमान के साथ npm install connect, जो इस पोस्ट के समान एक गीथब से काफी अलग दिखता है)। जब सर्वर को एक रिक्वेस्ट मिलती है, तो वह स्टैक से अधिक पुनरावृत्ति करता है, (request, response, next)विधि कहलाता है ।

समस्या यह है, यदि किसी मिडलवेयर आइटम में प्रतिक्रिया बॉडी या हेडर को लिखी जाती है (ऐसा लगता है कि यह या तो / या किसी कारण से है), लेकिन कॉल नहीं करता है response.end()और आप कॉल करते हैंnext() तो जैसे ही कोर Server.prototype.handleविधि पूरी होती है, यह नोटिस होने वाला है उस:

  1. स्टैक में और आइटम नहीं हैं, और / या
  2. कि 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(), जो कनेक्ट सर्वर को भ्रमित करता है।


7
+1 यह एक महान व्याख्या है, लेकिन जब आप res.redirect () का उपयोग करते हैं तो इस मामले के बारे में क्या है? मैं अक्सर इस समस्या में चला जाता हूं जब मिडलवेयर कुछ स्थिति के आधार पर पुनर्निर्देशित करने की कोशिश कर रहा होता है। क्या मिडलवेयर को आपके "गुड मिडलवेयर" उदाहरण के अनुसार रीडायरेक्ट नहीं किया जाना चाहिए?
क्षोदिनेजा

आप जानते हैं कि आपके पास एक समस्याग्रस्त मिडलवेयर होने के कारण मुझे यह सटीक समस्या है, हालांकि मुझे एक ऐसे मामले की आवश्यकता है जहां मैं प्रतिक्रिया देता हूं लेकिन श्रृंखला के हिस्से के रूप में एक अलग नियंत्रक में आगे की प्रक्रिया करना चाहता हूं, मैं इस त्रुटि को कैसे दबाऊं ?
क्यू।

57

इस प्रश्नोत्तर में कुछ उत्तर गलत हैं। स्वीकृत उत्तर भी बहुत "व्यावहारिक" नहीं है, इसलिए मैं एक जवाब पोस्ट करना चाहता हूं जो चीजों को सरल शब्दों में समझाता है। मेरा उत्तर उन 99% त्रुटियों को कवर करेगा जिन्हें मैं बार-बार पोस्ट करता हूँ। त्रुटि के पीछे के वास्तविक कारणों के लिए स्वीकृत उत्तर पर एक नज़र डालें।


HTTP एक चक्र का उपयोग करता है जिसे प्रति अनुरोध एक प्रतिक्रिया की आवश्यकता होती है। जब ग्राहक एक अनुरोध (जैसे POST या GET) भेजता है तो सर्वर को केवल एक प्रतिसाद भेजना चाहिए।

यह त्रुटि संदेश:

त्रुटि: भेजे जाने के बाद हेडर सेट नहीं कर सकते।

आमतौर पर तब होता है जब आप एक अनुरोध के लिए कई प्रतिक्रियाएँ भेजते हैं। सुनिश्चित करें कि निम्नलिखित कार्यों को केवल एक बार अनुरोध के अनुसार कहा जाता है:

  • res.json()
  • res.send()
  • res.redirect()
  • res.render()

(और कुछ और जो शायद ही कभी उपयोग किए जाते हैं, स्वीकृत उत्तर की जांच करें)

इन कॉल फ़ंक्शन को कॉल करने पर रूट कॉलबैक वापस नहीं आएगा। यह तब तक चलता रहेगा जब तक कि यह फ़ंक्शन के अंत या रिटर्न स्टेटमेंट को हिट न कर दे। आप जब एक जवाब भेजने से वापस जाने के लिए चाहते हैं तो आप यह इतना पसंद कर सकते हैं: 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 अनुरोध / एपीआई / रूट 1 पर भेजा जाता है तो यह कॉलबैक में हर पंक्ति को चलाएगा। एक Can हेडर सेट नहीं के बाद वे भेजे जाते हैं त्रुटि संदेश क्योंकि फेंक दिया जाएगा 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);
});

एक बड़ा पापी अतुल्यकालिक कार्य है। उदाहरण के लिए, इस प्रश्न से कार्य लें :

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()res.json(doc2)में elseतो कहा जाएगा। अब दो प्रतिक्रियाएँ भेजी गई हैं और हेडर त्रुटि संदेश सेट नहीं हो सकता है।

इस मामले में, फिक्स को हटाना होगा res.json(doc1)। क्लाइंट को दोनों डॉक्स वापस भेजने के res.json()लिए अन्य के रूप में लिखा जा सकता है res.json({ article: doc1, user: doc2 })


2
आप एक अतुल्यकालिक समारोह के अंदर हैं, और चाहिएreturnres.json
Genovo

मेरा मुद्दा res.sendलूप के लिए उपयोग कर रहा था ।
मैहान निजत

1
इसने मुझे इस मुद्दे को समझने और ठीक करने के लिए अंत में मदद की, धन्यवाद बहुत कुछ :)
पंकज पारकर

बहुत बहुत धन्यवाद आप मेरा समय बचाते हैं।
मोहम्मद फैसल

यह निश्चित रूप से सबसे अच्छा जवाब है!
जुआन मेनेंडेज़

53

मेरे पास यह एक ही मुद्दा था और यह एहसास हुआ कि क्योंकि मैं res.redirectएक returnबयान के बिना बुला रहा था , इसलिए 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();
};

43

बहुत से लोगों ने इस त्रुटि को मारा। यह async प्रसंस्करण के साथ एक भ्रामक है। सबसे अधिक संभावना है कि आपका कुछ कोड पहले टिक में हेडर सेट कर रहा है और फिर आप भविष्य में टिक में एक async कॉलबैक चला रहे हैं। बीच में, प्रतिक्रिया हेडर भेजा जाता है, लेकिन फिर हेडर (जैसे एक 30X रीडायरेक्ट) अतिरिक्त हेडर जोड़ने की कोशिश करते हैं, लेकिन यह बहुत देर हो चुकी है क्योंकि प्रतिक्रिया हेडर पहले ही प्रेषित हो चुका है।

मुझे यकीन नहीं है कि आपकी त्रुटि का कारण क्या है, लेकिन जांच के लिए संभावित क्षेत्रों के रूप में किसी भी कॉलबैक को देखें।

अपने कोड को सरल बनाने के लिए एक आसान टिप। छुटकारा पाएं app.configure()और app.useसीधे अपने शीर्ष स्तर के दायरे में सीधे कॉल करें ।

एवरीथ मॉड्यूल भी देखें , जो फेसबुक और एक दर्जन या अन्य 3 पार्टी प्रमाणीकरण प्रदाता है।


एक 30X पुनर्निर्देशन एक HTTP प्रतिक्रिया कोड है। w3.org/Protocols/rfc2616/rfc2616-sec10.html कोड 300-399 रीडायरेक्शन के विभिन्न रूप हैं, 302 और 301 आमतौर पर क्लाइंट को वैकल्पिक URL पर भेजने के लिए उपयोग किए जाते हैं। जब आप नोड में response.redirect (...) करते हैं, तो प्रतिक्रिया में एक 30X रीडायरेक्ट हेडर भेजा जाएगा।
पीटर लियोंस

3
ओह। मैं एक पंक्ति या कुछ में 30 रीडायरेक्ट की कल्पना कर रहा था
जनक मीना

17

मैंने इस मुद्दे पर अपना सिर हिलाया और कॉलबैक को संभालने में लापरवाही के कारण ऐसा हुआ। गैर-वापसी कॉलबैक दो बार सेट होने की प्रतिक्रिया का कारण बनता है! "

मेरे कार्यक्रम में एक कोड था जो अनुरोध को मान्य करता है और DB को क्वेरी करता है। सत्यापन के बाद यदि त्रुटि है, तो मैं सत्यापन त्रुटियों के साथ index.js को वापस बुला रहा था। और यदि सत्यापन पास हो जाता है तो यह आगे बढ़ता है और db को सफलता / असफलता से टकराता है।

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

क्या हो रहा था: इंसेज़ सत्यापन कॉलबैक विफल हो जाता है और प्रतिक्रिया सेट हो जाती है। लेकिन वापस नहीं लौटा। तो यह अभी भी जारी है विधि DB और हिट सफलता / विफलता के लिए चला जाता है। यह उसी कॉलबैक को फिर से कॉल करता है जिससे प्रतिक्रिया दो बार सेट होती है।

इसलिए समाधान सरल है, आपको कॉलबैक को 'वापस' करने की आवश्यकता है ताकि विधि निष्पादित न हो जाए, एक बार त्रुटि हुई है और इसलिए एक बार प्रतिक्रिया ऑब्जेक्ट सेट करें

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

1
धन्यवाद! यह मेरी समस्या भी है। बस एक ctrl + f किया और इसके callback(...)बिना एक return;ऐसा पाया जो अंततः res.send(...)दो बार बुलाया जा रहा था ।

15

इस प्रकार की त्रुटि आपको तब मिलेगी जब आप प्रतिक्रिया भेजने के बाद स्टेटमेंट पास करेंगे।

उदाहरण के लिए:

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

आपके द्वारा देखी जा रही त्रुटि का परिणाम होगा, क्योंकि एक बार प्रतिक्रिया भेजे जाने के बाद, निम्नलिखित res.sendको निष्पादित नहीं किया जाएगा।

यदि आप कुछ भी करना चाहते हैं, तो आपको प्रतिक्रिया भेजने से पहले करना चाहिए।


यह मेरा सटीक मुद्दा था :)
जोएल बामर

6

कभी-कभी आपको यह त्रुटि तब हो सकती है जब आप res.end या res.send के बाद अगले () फ़ंक्शन को कॉल करने का प्रयास करते हैं , यदि आप अपने फ़ंक्शन में res.send या res.end के बाद अगला () है तो हटाने का प्रयास करें। नोट: यहां अगले () का अर्थ है कि आपकी प्रतिक्रिया के साथ ग्राहक को जवाब देने के बाद ( यानी res.send या res.end ) आप अभी भी फिर से प्रतिक्रिया देने के लिए कुछ कोड निष्पादित करने का प्रयास कर रहे हैं, इसलिए यह कानूनी नहीं है।

उदाहरण :

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

next()उपरोक्त फ़ंक्शन से निकालें और यह काम करेगा।


6

यदि आप ब्लॉक के returnबाद कॉलबैक फ़ंक्शन का उपयोग कर रहे हैं err। यह उन परिदृश्यों में से एक है जिसमें यह त्रुटि हो सकती है।

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और एक्सप्रेस पर परीक्षण किया गया4.16.4


4

यह त्रुटि तब होती है जब आप 2 प्रतिक्रियाएँ भेजते हैं। उदाहरण के लिए :

if(condition A)
{ 

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

}

if (condition B){

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

कल्पना कीजिए कि अगर किसी कारणवश A और B सही हैं तो दूसरे में renderआपको वह त्रुटि मिलेगी


3

मेरे मामले में यह एक 304 प्रतिक्रिया (कैशिंग) थी जो इस मुद्दे का कारण बन रही थी।

सबसे आसान समाधान:

app.disable('etag');

यदि आप अधिक नियंत्रण चाहते हैं तो यहां वैकल्पिक समाधान:

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


मेरे मामले में भी 304 की प्रतिक्रिया। मैं प्रसंस्करण के लिए फाइबर का उपयोग कर रहा हूं। किसी भी तरह से आपका जवाब बहुत मदद करता है। धन्यवाद
दिलीप स्टेनली

क्या कोई यह बता सकता है कि etag हेडर को हटाने के क्या निहितार्थ हैं?
मट्टविल्स

2
ETags सर्वर को ऐसी सामग्री भेजने की अनुमति नहीं देता है जो परिवर्तित नहीं हुई है। इसे बंद करना इस सुविधा को अक्षम करता है। ETag विकिपीडिया प्रविष्टि ( en.wikipedia.org/wiki/HTTP_ETag ) की एक लंबी व्याख्या है।
ब्लेंड किया

3

मेरे मामले में यह प्रतिक्रिया और post..s के साथ हुआ जब मैंने componentWillUnmountअपने रिएक्ट घटक के कॉलबैक में एक चैनल से सदस्यता समाप्त नहीं की ।


2

किसी के लिए भी यह आ रहा है और अन्य समाधानों में से किसी ने भी मदद नहीं की, मेरे मामले में यह एक ऐसे मार्ग पर प्रकट हुआ, जिसने छवि अपलोडिंग को संभाला लेकिन टाइमआउट को हैंडल नहीं किया , और इस तरह जब कॉलबैक को निकाल दिया गया था, तो अपलोड बहुत लंबा और समय समाप्त हो गया। समयबाह्य प्रतिक्रिया भेजे जाने के बाद , res.send () कॉलिंग क्रैश हो गई क्योंकि हेडर पहले से ही टाइमआउट के लिए पहले से ही निर्धारित थे।

यह बहुत ही कम समय निर्धारित करके और एक शालीनता-बड़ी छवि के साथ मार्ग को हिट करके आसानी से पुन: पेश किया गया, हर बार दुर्घटना को पुन: प्रस्तुत किया गया।


1
इससे बचने के लिए आपने टाइमआउट को कैसे हैंडल किया?

2

बस ये झुक गया। आप इस फ़ंक्शन के माध्यम से प्रतिक्रियाएं पास कर सकते हैं:

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

2

इस मिडलवेयर को जोड़ें और यह काम करेगा

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

2

ऐसा तब होता है जब ग्राहक को प्रतिक्रिया दी गई थी और फिर से आप प्रतिक्रिया देने का प्रयास कर रहे हैं। आपको अपने कोड में जांचना होगा कि कहीं आप फिर से क्लाइंट को प्रतिक्रिया दे रहे हैं जो इस त्रुटि का कारण बनता है। जब आप वापस लौटना चाहते हैं तो एक बार प्रतिक्रिया देखें और वापस करें।


1

जब मैं वादों से घिर रहा था तब मेरे पास यह मुद्दा था। एक वादा के अंदर एक वादा 200 सर्वर पर वापस आ जाएगा, लेकिन तब बाहरी वादा का कैच स्टेटमेंट 500 वापस कर देगा। एक बार जब मैंने यह तय किया, तो समस्या दूर हो गई।


आपने इसे ठीक कैसे किया? मेरे पास वादों के साथ यही मुद्दा है। मैं उन्हें घोंसले के शिकार से बचने नहीं कर सकता ... तो मैं वापसी विवरण पर निष्पादन कैसे रोकूं?
सौरभ

1

Nuxt से यहां आया था, समस्या घटक की asyncDataविधि में थी, मैं returnवादा करना भूल गया था जो डेटा ला रहा था और वहां हेडर सेट कर रहा था।


1

कृपया जांचें कि क्या आपका कोड एकल अनुरोध के लिए कई res.send () स्टेटमेंट लौटा रहा है। जैसे जब मेरे पास यह मुद्दा था ...।

मैं अपने पुनर्स्थापना नोड आवेदन में यह मुद्दा था। गलती यह थी कि

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

मैं ब्रेक लिखने के बिना स्विच का उपयोग करके विभिन्न मामलों को संभाल रहा था। उन लोगों के लिए जो स्विच केस से परिचित हैं, जानते हैं कि ब्रेक के बिना, कीवर्ड वापस करें। मामले के तहत कोड और इसकी अगली पंक्तियों पर अमल किया जाएगा, चाहे जो भी हो। इसलिए भले ही मैं एक ही 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; }


आपकी प्रेरणा के लिए धन्यवाद, मेरे साथ भी ऐसा ही हुआ। मैंने शर्त के साथ इसे हल भी किया।
अमर अब्देलरहमान

1

यह बहुत अधिक संभावना है कि यह एक नोड चीज़ से अधिक है, 99% समय यह एक डबल कॉलबैक है जिसके कारण आप दो बार जवाब दे सकते हैं, या अगले () आईएनजी दो बार आदि, निश्चित रूप से। यह हल मेरी समस्या अगले () लूप के अंदर का उपयोग कर रहा था। लूप से अगला () निकालें या इसे एक से अधिक बार कॉल करना बंद करें।


1

मुझे एक समान त्रुटि मिली जब मैंने लूप फ़ंक्शन के भीतर प्रतिक्रिया भेजने की कोशिश की। सरल समाधान के लिए कदम था

res.send ('प्रतिक्रिया भेजें');

लूप से बाहर निकलने के बाद से आप केवल एक बार प्रतिक्रिया हैडर भेज सकते हैं।

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



1

मुझे वही समस्या थी जो मैंगोज़ के कारण हुई थी।

यह तय करने के लिए कि आपको सक्षम होना चाहिए Promises, ताकि आप जोड़ सकें: mongoose.Promise = global.Promiseअपने कोड में, जो उपयोग करने में सक्षम करता है native js promises

इस समाधान के अन्य विकल्प हैं:

var mongoose = require('mongoose');
// set Promise provider to bluebird
mongoose.Promise = require('bluebird');

तथा

// q
mongoose.Promise = require('q').Promise;

लेकिन आपको पहले इन पैकेजों को स्थापित करने की आवश्यकता है।


1

RND के बाद त्रुटि अपने आप मिल जाती है:

1) मेरा त्रुटि कोड:

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

2) मेरा सक्सेस कोड

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

अंतर यह है कि मैं प्रयोग किया जाता है sendStatus () के बजाय स्थिति ()


0

टाइपस्क्रिप्ट में, मेरा मुद्दा यह था कि मैं एक संदेश प्राप्त करने के बाद वेबसैट कनेक्शन को बंद नहीं करता था।

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

0

यदि आपको ऊपर से सहायता नहीं मिलती है: noobs के लिए: इस त्रुटि के पीछे कारण कई बार अनुरोध भेज रहा है तो आइए कुछ मामलों से समझते हैं: - 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();   
        }

`ऊपर की कॉलिंग में अगला () दो बार एक त्रुटि बढ़ाएगा

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

यहां जवाब दो बार भेजा गया है कि क्या आपने पहले ही जवाब भेज दिया है


0

मेरे मामले में यह कई कॉलबैक के कारण होता है। मैंने next()कोड के दौरान विधि को कई बार कॉल किया है


0

मेरा मुद्दा यह था कि मेरे पास एक setIntervalदौड़ थी, जिसमें एक if/elseब्लॉक था, जहां clearIntervalविधि अंदर थी else:

      const dataExistsInterval = setInterval(async () => {
        const dataExists = Object.keys(req.body).length !== 0;
        if (dataExists) {
          if (!req.files.length) {
            return res.json({ msg: false });
          } else {
              clearInterval(dataExistsInterval);
            try {
            . . .

लाना clearIntervalपहले if/elseचाल किया था।


0

मेरे मामले में, एक पाश में, मैंने कहा res.render()कि कई बार कॉल करने की कोशिश की गई हो सकती है।


-1

इस त्रुटि के मामले में मुझे सब करना था res.end ()।

 auth.annonymousOnly = function(req, res, next) {
 // add other task here   
   res.end();    
  };

दूसरी समस्या जिसका आपको सामना करना पड़ सकता है, वह है Res.json और Res के बाद का कोड। लिखो। इस मामले में, आपको उसके बाद निष्पादन को रोकने के लिए रिटर्न का उपयोग करने की आवश्यकता है।

 auth.annonymousOnly = function(req, res, next) {

  if(!req.body.name)
  {
    res.json({error:"some error"});
    return;
  }
  let comp = "value"; // this is the code after res.json which may cause some problems so you have to use return 
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.