ত্রুটি: ক্লায়েন্টকে প্রেরণের পরে শিরোনাম সেট করা যায় না


724

আমি নোড.জেজে মোটামুটি নতুন এবং আমার কিছু সমস্যা হচ্ছে।

আমি নোড.জেএস 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
গুগল আমাকে এই প্রশ্নে প্রেরণ করেছে, তবে এক্সপ্রেসজেএস এর নতুন সংস্করণগুলিতে রেস.হেডারস সেন্টার বুলিয়ান রয়েছে যা হেডারগুলি সেট / প্রেরণ করা নিরাপদ কিনা তা পরীক্ষা করতে ব্যবহার করা যেতে পারে
জুলিয়ান সোরো

উত্তর:


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 ত্রুটি পৃষ্ঠা পাঠানোর চেষ্টা করেছিল। শিরোনামগুলি ইতিমধ্যে প্রেরণ করা setHeaderহওয়ায় নোড.জেস আপনার ত্রুটিটি দেখে ফেলেছিল।

নোড.জেএস / এক্সপ্রেস প্রতিক্রিয়া পদ্ধতিগুলির ਵਿਸ਼ਾਲ তালিকা এবং কখন তাদের ডাকতে হবে:

রেসপন্স হতে হবে হেড এবং থাকবে হেড :

  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])

রেসপন্স পারেন হতে পারে হেড / body এবং দেহাবশেষ দেহ :

  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
এই ক্লাসিক ভুলটির জন্যও নজর রাখুন: পুনঃনির্দেশ () বিবৃতি কার্যকর করা থামায় না ... সুতরাং এর পরে ফিরে আসুন। অন্যথায় অন্যান্য কোড কার্যকর করা যেতে পারে যা অবিচ্ছিন্নভাবে বিখ্যাত শিরোনাম ত্রুটির কারণ হতে পারে। থ্যাঙ্কস এর ব্যাখ্যার জন্য!
লুজেন

এটি এড়াতে সাধারণত আপনার কলব্যাকের শেষে রিটার্ন ব্যবহার করা ভাল ধারণা
থেঠাকুরি

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.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 এটি দুর্দান্ত ব্যাখ্যা, তবে আপনি যখন রেস-ডায়রেক্ট () ব্যবহার করেন তখন কী হবে? মিডলওয়্যার যখন কিছু শর্তের ভিত্তিতে পুনঃনির্দেশের চেষ্টা করে তখন আমি প্রায়শই এই সমস্যাটিতে চলে যাই। আপনার "গুড মিডলওয়্যার" উদাহরণ অনুসারে মিডলওয়্যারগুলি পুনর্নির্দেশ করা উচিত নয়?
কোডেনিনজা

আপনি জানেন যে আপনি সমস্যাযুক্ত মিডলওয়্যারটি বলছেন তার কারণে আমার এই সঠিক সমস্যাটি রয়েছে, তবে আমার এমন একটি মামলা দরকার যেখানে আমি প্রতিক্রিয়া ফিরিয়েছি তবে শৃঙ্খলের অংশ হিসাবে একটি পৃথক নিয়ামকটিতে আরও প্রসেসিং করতে চাই, আমি কীভাবে এই ত্রুটিটি দমন করতে যাব? ?
আইকিউ।

57

এই প্রশ্নোত্তরের কয়েকটি উত্তর ভুল। গৃহীত উত্তরটিও খুব "ব্যবহারিক" নয়, তাই আমি এমন একটি উত্তর পোস্ট করতে চাই যা বিষয়গুলিকে সহজ শর্তে ব্যাখ্যা করে। আমার উত্তরটিতে বারবার পোস্ট করা ত্রুটিগুলির 99% অংশ কভার করা হবে। ত্রুটির পিছনে প্রকৃত কারণে গ্রহণযোগ্য উত্তরটি একবার দেখুন।


এইচটিটিপি একটি চক্র ব্যবহার করে যার প্রতি অনুরোধের জন্য একটি প্রতিক্রিয়া প্রয়োজন। যখন ক্লায়েন্ট কোনও অনুরোধ প্রেরণ করে (যেমন পোস্ট বা জিইটি) সার্ভারটি কেবল তখনই তার প্রতিক্রিয়া পাঠাতে হবে।

এই ত্রুটি বার্তা:

ত্রুটি: শিরোনামগুলি প্রেরণের পরে সেট করা যায় না।

সাধারণত যখন আপনি একটি অনুরোধের জন্য বেশ কয়েকটি প্রতিক্রিয়া প্রেরণ করেন তখনই ঘটে। নিশ্চিত হয়ে নিন যে অনুরোধের জন্য নিম্নলিখিত ক্রিয়াকলাপগুলি কেবল একবার কল করা হয়েছে:

  • 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' });
}

যখন কোনও পোস্টের অনুরোধটি / এপিআই / রুট 1 এ পাঠানো হয় এটি কলব্যাকের প্রতিটি লাইন চলবে run একটি ক্যান হেডার সেট না পরে তারা পাঠানো হয় ত্রুটির বার্তা কারণ ফেলে দেওয়া হবে 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 প্রক্রিয়াজাতকরণের সাথে বিভ্রান্তিকর। সম্ভবত আপনার কিছু কোড প্রথম টিকটিতে শিরোনাম স্থাপন করছে এবং তারপরে আপনি ভবিষ্যতের টিকটিতে একটি অ্যাসিঙ্ক কলব্যাক চালাচ্ছেন। এর মধ্যে, প্রতিক্রিয়া শিরোনামটি প্রেরণ হয়ে যায়, তবে তারপরে আরও শিরোনাম (30 এক্স পুনর্নির্দেশের মতো) অতিরিক্ত শিরোনাম যুক্ত করার চেষ্টা করে, তবে প্রতিক্রিয়া শিরোনামটি ইতিমধ্যে সংক্রামিত হওয়ার পরে অনেক দেরি হয়ে গেছে।

আপনার ত্রুটিটি ঠিক কী কারণে ঘটছে তা আমি নিশ্চিত নই, তবে তদন্তের সম্ভাব্য ক্ষেত্র হিসাবে কোনও কলব্যাকগুলি দেখুন।

আপনার কোড সহজ করার জন্য একটি সহজ পরামর্শ ip পরিত্রাণ পান app.configure()এবং app.useসরাসরি আপনার শীর্ষ স্তরের সুযোগে কল করুন ।

Everyauth মডিউলটিও দেখুন , যা ফেসবুক এবং এক ডজন বা তৃতীয় পক্ষের প্রমাণীকরণ সরবরাহকারী করে।


একটি 30 এক্স পুনর্নির্দেশ একটি HTTP প্রতিক্রিয়া কোড response w3.org/Protocols/rfc2616/rfc2616-sec10.html কোডস 300-399 পুনর্নির্দেশের বিভিন্ন প্রকরণ, 302 এবং 301 সাধারণত ক্লায়েন্টকে একটি বিকল্প URL এ প্রেরণে ব্যবহৃত হয়। আপনি নোডে রেসপন্স.ডাইরেক্ট (...) করলে, 30X রিডাইরেক্ট শিরোনাম প্রতিক্রিয়াতে প্রেরণ করা হবে।
পিটার লিয়নস

3
Ohhhh। আমি এক সারি বা 30 টি 30 টি পুনর্নির্দেশের কল্পনা করছিলাম
জানাক মীনা

17

আমি এই বিষয়টি নিয়ে আমার মাথাটি সিদ্ধ করেছি এবং কলব্যাকগুলি পরিচালনা করার ক্ষেত্রে একটি গাফিল ভুলের কারণে এটি ঘটেছে। নন রিটার্নড কলব্যাকগুলির কারণে প্রতিক্রিয়াটি দু'বার সেট করা যায়!

আমার প্রোগ্রামে একটি কোড ছিল যা অনুরোধকে বৈধ করে ডিবিকে জিজ্ঞাসা করে। ত্রুটি থাকলে বৈধতা দেওয়ার পরে, আমি বৈধতা ত্রুটিগুলি সহ সূচক.জেএসকে ফিরে কল করছিলাম। এবং যদি বৈধতা পাস হয় এটি এগিয়ে যায় এবং সাফল্য / ব্যর্থতার সাথে ডিবিতে আঘাত করে।

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

যা হচ্ছিল তা হ'ল: বৈধতা যাচাই করা কলব্যাক কল করতে ব্যর্থ হয় এবং প্রতিক্রিয়া সেট হয়ে যায়। তবে ফিরে আসেনি। সুতরাং এটি এখনও অব্যাহত রয়েছে পদ্ধতিটি ডিবিতে চলে আসে এবং সাফল্য / ব্যর্থতা হিট করে। এটি আবার একই কলব্যাককে কল দেয় যাতে প্রতিক্রিয়া এখন দু'বার সেট হয়ে যায়।

সমাধানটি সহজ, আপনার কলব্যাকটি 'রিটার্ন' করা দরকার যাতে ত্রুটি দেখা দেওয়ার পরে পদ্ধতিটি চালানো অবিরত না করে এবং প্রতিক্রিয়া অবজেক্টটি একবার সেট করে once

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

1
ধন্যবাদ! এটি আমার সমস্যাও হয়ে উঠল। কেবলমাত্র একটি সিটিআরএল + এফ করেছে এবং এটির পরেও callback(...)একটি পাওয়া গেছে return;যা শেষ পর্যন্ত res.send(...)দু'বার ডেকে আনে।

15

প্রতিক্রিয়া প্রেরণের পরে আপনি বিবৃতিগুলি পাস করার সময় এই ধরণের ত্রুটিটি পাবেন।

উদাহরণ স্বরূপ:

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

আপনি যে ত্রুটিটি দেখছেন তার ফলস্বরূপ, কারণ একবার প্রতিক্রিয়া প্রেরণ করা হয়ে গেলে, নিম্নলিখিতগুলি res.sendকার্যকর করা হবে না।

আপনি যদি কিছু করতে চান তবে প্রতিক্রিয়া প্রেরণের আগে আপনার এটি করা উচিত।


এটি আমার সঠিক সমস্যা ছিল :)
জোয়েল বাল্মার

6

কখনও কখনও আপনি এই ত্রুটিটি পেতে পারেন যখন আপনি রেসেন্ড বা পুনরায় বিক্রয় করার পরে পরবর্তী () ফাংশনটিতে কল করার চেষ্টা করবেন, আপনার ফাংশনে পুনরায় বিক্রয় বা পুনরায় বিক্রয় করার পরে পরবর্তী () থাকলে মুছার চেষ্টা করুন। দ্রষ্টব্য: এখানে পরবর্তী () এর অর্থ ক্লায়েন্টকে আপনার প্রতিক্রিয়া দিয়ে প্রতিক্রিয়া জানানোর পরে ( অর্থাত্ পুনরায় বিক্রয় বা পুনরায় বিক্রয় করুন ) আপনি এখনও কিছু প্রতিক্রিয়া জানাতে কিছু কোড চালানোর চেষ্টা করছেন যাতে এটি আইনী নয়।

উদাহরণ:

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 প্রতিক্রিয়া। আমি প্রক্রিয়াজাতকরণের জন্য ফাইবার্স ব্যবহার করছি। আপনার উত্তর যে কোনও উপায়ে অনেক সাহায্য করে। আপনাকে ধন্যবাদ
দিলিপ স্ট্যানলি

ইটাগ শিরোলেখ অপসারণের জন্য কী কী প্রভাব বোঝাতে পারে?
ম্যাটউইলসন

2
ETags সার্ভারকে এমন সামগ্রী প্রেরণের অনুমতি দেয় যা পরিবর্তন হয়নি। এটি বন্ধ করা এই বৈশিষ্ট্যটি অক্ষম করে। ইটাগ উইকিপিডিয়া এন্ট্রি ( en.wikedia.org/wiki/HTTP_ETag ) এর দীর্ঘতর ব্যাখ্যা রয়েছে।
24:25

3

আমার ক্ষেত্রে এটি প্রতিক্রিয়া এবং পোস্টাল.জ এর সাথে ঘটেছিল যখন আমি componentWillUnmountআমার প্রতিক্রিয়া উপাদানটির কলব্যাকে কোনও চ্যানেল থেকে সাবস্ক্রাইব না করি ।


2

যে কারও কাছে এটি আসছে এবং অন্য সমাধানগুলির কোনওটিই সহায়তা করেনি, আমার ক্ষেত্রে এটি এমন একটি রুটে প্রকাশিত হয়েছিল যা চিত্র আপলোডিং পরিচালনা করে তবে সময়সীমা হ্যান্ডেল করে না , এবং কলব্যাকটি নিষ্ক্রিয় হওয়ার পরে যদি আপলোডটি খুব দীর্ঘ এবং সময়সীমা অতিক্রম করে if টাইমআউট প্রতিক্রিয়া প্রেরণের পরে , পুনরায় বিক্রয় করুন () কে কল করার ফলে ক্র্যাশ ঘটেছিল কারণ শিরোনামগুলি ইতিমধ্যে সময়সীমার জন্য অ্যাকাউন্টে সেট করা ছিল।

খুব সহজেই একটি সংক্ষিপ্ত সময়সীমা নির্ধারণ করে এবং একটি শালীন-বৃহত চিত্র সহ রুটটিকে আঘাত করে সহজেই পুনরুত্পাদন করা হয়েছিল, প্রতিবার ক্র্যাশটি পুনরুত্পাদন করা হয়েছিল।


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 ফিরিয়ে দেবে I আমি এটি স্থির করার পরে সমস্যাটি চলে গেল।


আপনি ঠিক কিভাবে এটি ঠিক করেছেন? প্রতিশ্রুতি নিয়ে আমারও একই সমস্যা আছে। আমি তাদের বাসা বাঁধতে পারছি না ... সুতরাং আমি কীভাবে রিটার্ন স্টেটমেন্টে ফাঁসি কার্যকর করব?
সৌরভ

1

থেকে এখানে আসার nuxt , সমস্যা উপাদান এর মধ্যে ছিল asyncDataপদ্ধতি, আমি ভুলে গেছি returnপ্রতিজ্ঞা কোন ডেটা আনার সময় এবং হেডার সেখানে সেটিং।


1

আপনার কোডটি একক অনুরোধের জন্য একাধিক পুনঃ বিক্রয় () বিবৃতি পাঠাচ্ছে কিনা তা পরীক্ষা করে দেখুন। আমার যখন এই সমস্যাটি হয়েছিল তখন ভালো লাগে ...

আমার পুনর্নির্মাণ নোড অ্যাপ্লিকেশনটিতে আমি এই সমস্যাটি ছিল। ভুল ছিল

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

আমি বিরতি না লিখে সুইচ ব্যবহার করে বিভিন্ন মামলা পরিচালনা করছি। সুইচ কেসের সাথে সামান্য পরিচিত যারা জানেন যে বিরতি ছাড়াই, কীওয়ার্ডগুলি ফেরান। কেস এর অধীন কোড এবং এর পরবর্তী লাইনগুলি নির্ধারণ করা হবে যাই হোক না কেন। যদিও আমি একক রেসডেন্ড পাঠাতে চাইছি, তবুও এই ভুলের কারণে এটি একাধিক রেস.সেটেন্ড স্টেটমেন্টগুলি ফিরিয়েছিল যা প্ররোচিত হয়েছিল

ক্লায়েন্টকে প্রেরণের পরে ত্রুটি ক্যান্ট শিরোনাম সেট করে। যা প্রতিটি যোগ করার আগে রিটার্নটি যুক্ত করে বা রিটার্ন ব্যবহারের মাধ্যমে রিটার্ন ব্যবহার করে সমাধান হয়েছে (রিটার্ন রেস.সেন্ড (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

কোনও আরএনডির পরে ত্রুটি নিজেই খুঁজে পেতে পারে:

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

যদি আপনি উপরে থেকে সহায়তা না পান: নুবস জন্য এই ত্রুটির কারণটি একাধিকবার অনুরোধ পাঠাচ্ছে আসুন কিছু ক্ষেত্রে থেকে বুঝতে পারি: - ১ `

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

above উপরের কলিংয়ে পরবর্তী () দুবার ত্রুটি বাড়িয়ে তুলবে

  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কৌতুক করেনি।



-1

এই ত্রুটির ক্ষেত্রে আমাকে যা করতে হয়েছিল তা হ'ল রিসেন্ড ()।

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

অন্য যে সমস্যার মুখোমুখি হতে পারেন তা হ'ল রেস.জেসন এবং রেজিসের পরে কোড রয়েছে। অনুগ্রহ করে লিখুন। এই ক্ষেত্রে, এর পরে কার্যকর করা বন্ধ করতে আপনাকে রিটার্ন ব্যবহার করতে হবে।

 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 
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.