Hata: Başlıklar istemciye gönderildikten sonra ayarlanamaz


727

Node.js için oldukça yeniyim ve bazı sorunlar yaşıyorum.

Node.js 4.10 ve Express 2.4.3 kullanıyorum.

Ben erişim çalıştığınızda http://127.0.0.1:8888/auth/facebook i yönlendirileceksiniz http://127.0.0.1:8888/auth/facebook_callback .

Daha sonra aşağıdaki hatayı aldım:

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)

Kodum şudur:

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

Kodumda neyin yanlış olduğunu bilebilir miyim?


visionmedia'dan basit cevap: github.com/visionmedia/express/issues/634
shi11i

2
Google beni bu soruya gönderdi, ancak yeni ExpressJS sürümlerinde res.headersSent boolean var, bu da başlık ayarlamak / göndermek için güvenli olup olmadığını kontrol etmek için kullanılabilir
Julian Soro

Yanıtlar:


1115

resExpress'te nesne bir alt sınıfıdır node.js enhttp.ServerResponse ( http.js kaynağını okuma ). res.setHeader(name, value)Arayana kadar istediğiniz sıklıkta arama yapmanıza izin verilir res.writeHead(statusCode). Sonra writeHead, başlıklar pişirilir ve sadece arayabilir res.write(data)ve son olarakres.end(data) .

"Hata: Üstbilgiler gönderildikten sonra ayarlanamıyor" hatası. zaten Gövde veya Bitmiş durumunda olduğunuz anlamına gelir, ancak bazı işlevler bir başlık veya statusCode ayarlamaya çalıştı. Bu hatayı gördüğünüzde, bir kısmı zaten yazıldıktan sonra başlık göndermeye çalışan herhangi bir şey aramaya çalışın. Örneğin, yanlışlıkla iki kez çağrılan geri çağrıları veya gövde gönderildikten sonra meydana gelen hataları arayın.

Sizin durumunuzda, aradınız res.redirect(), bu da yanıtın Bitmesine neden oldu. Sonra kodunuz bir hata ( res.reqis null) attı . ve hata gerçek function(req, res, next)(geri arama içinde değil) içinde gerçekleştiği için, Connect onu yakalamayı başardı ve ardından 500 hata sayfası göndermeye çalıştı. Ancak başlıklar zaten gönderildiğinden, Node.js setHeadergördüğünüz hatayı attı.

Node.js / Express yanıt yöntemlerinin kapsamlı bir listesi ve ne zaman çağrılmaları gerekir:

Tepki olmalıdır Başkanı ve kalır Başkanı :

  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]) (Yalnızca Express)
  7. res.charset = 'utf-8' (Yalnızca Express; yalnızca Express'e özgü yöntemleri etkiler)
  8. res.contentType(type) (Yalnızca Express)

Tepki Başın içinde olmalı ve Beden olur :

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

Tepki Ya olabilir Kafa / Gövde ve kalıntıların Gövde :

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

Tepki Baş / Gövde olabilir ve Bitmiş olur :

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

Tepki, Kafa / Bedende olabilir ve şu anki durumunda kalır:

  1. res.addTrailers(headers)

Tepki olmalıdır Başkanı ve olur Biten :

  1. return next([err]) (Yalnızca Connect / Express)
  2. Ara katman yazılımındaki istisnalar function(req, res, next) (yalnızca Connect / Express)
  3. res.send(body|status[, headers|status[, status]]) (Yalnızca Express)
  4. res.attachment(filename) (Yalnızca Express)
  5. res.sendfile(path[, options[, callback]]) (Yalnızca Express)
  6. res.json(obj[, headers|status[, status]]) (Yalnızca Express)
  7. res.redirect(url[, status]) (Yalnızca Express)
  8. res.cookie(name, val[, options]) (Yalnızca Express)
  9. res.clearCookie(name[, options]) (Yalnızca Express)
  10. res.render(view[, options[, fn]]) (Yalnızca Express)
  11. res.partial(view[, options]) (Yalnızca Express)

13
Evet, next () veya diğer cb'yi iki kez aramak için kontrol edin.
Tony Gutierrez

3
Hızlı bağlantılar ölü gibi görünüyor
Korhan Öztürk

25
Ayrıca bu klasik hataya dikkat edin: res.redirect () ifadenin yürütülmesini durdurmaz ... öyleyse bundan sonra geri dönün. Aksi takdirde, ünlü başlık hatasına yanlışlıkla neden olabilecek başka kodlar çalıştırılabilir. Açıklama için teşekkürler!
KLoozen

Bunu önlemek için geri
aramanın

4
Ara yazılımımda çok küçük bir hata yaptım, daha returnönce yapmadım next(), teşekkürler bu hataya dikkat çekti!
illcrx

113

Bir süre de bu hatayla karşılaştım. Sanırım (umut) Başımı etrafına sardım, referans için buraya yazmak istedim.

Yöntemi kullanarak bağlanmak veya ifade etmek için ara katman yazılımı eklediğinizde (bağlanma üzerine kuruludur), bağlantıya app.useöğeleri eklersiniz Server.prototype.stack(En azından akımla npm install connect, bu yazıdan itibaren bir github'dan oldukça farklı görünüyor). Sunucu bir istek aldığında, (request, response, next)yöntemi çağırarak yığın üzerinden yineler .

Sorun, ara katman öğelerinden birinde yanıt gövdesine veya başlıklarına yazarsa (ya / veya herhangi bir nedenden dolayı görünüyor), ancak çağırmaz response.end()venext() çekirdek Server.prototype.handleyöntem tamamlandığında çağırırsınız , fark edeceksiniz o:

  1. yığınta başka öğe yok ve / veya
  2. bu response.headerSentdoğru.

Yani bir hata veriyor. Ancak attığı hata sadece bu temel yanıttır (connect http.jskaynak kodundan:

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

Tam orada, yönteminizde res.setHeader('Content-Type', 'text/plain');ayarlamış olduğunuz büyük olasılıkla render, response.end () öğesini çağırmadan şunu çağırıyor :

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

Her şeyin yapılandırılması gerektiği gibi:

İyi Ara Yazılım

// 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);

Sorunlu Ara Katman

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

Sorunlu ara katman, yanıt başlığını aramayı response.end()ve aramaları yapmadan ayarlar next(), bu da connect sunucusunu karıştırır.


7
+1 Bu harika bir açıklama ama res.redirect () kullandığınızda durum ne olacak? Middleware bazı koşullara göre yeniden yönlendirmeye çalışırken sık sık bu sorunla karşılaşıyorum. Ara katman yazılımı "İyi Ara katman yazılımı" örneğinize göre yönlendirilmemeli mi?
qodeninja

Sorunlu bir ara katman yazılımı olarak adlandırdığınız için tam olarak bu sorunun olduğunu biliyorsunuz, ancak yanıtı döndürdüğüm bir davaya ihtiyacım var, ancak zincirin bir parçası olarak ayrı bir denetleyicide daha fazla işlem yapmak istiyorum, bu hatayı bastırmaya nasıl gidebilirim ?
iQ.

57

Bu soru-cevap bölümündeki cevapların bazıları yanlış. Kabul edilen cevap da çok "pratik" değildir, bu yüzden işleri daha basit terimlerle açıklayan bir cevap göndermek istiyorum. Cevabım, tekrar tekrar yayınlandığını gördüğüm hataların% 99'unu kapsayacak. Hatanın arkasındaki gerçek nedenlerden dolayı kabul edilen cevaba bakınız.


HTTP, istek başına bir yanıt gerektiren bir döngü kullanır. İstemci bir istek gönderdiğinde (örneğin POST veya GET), sunucu buna yalnızca bir yanıt göndermelidir.

Bu hata mesajı:

Hata: Başlıklar gönderildikten sonra ayarlanamaz.

genellikle bir istek için birkaç yanıt gönderdiğinizde olur. Aşağıdaki işlevlerin istek başına yalnızca bir kez çağrıldığından emin olun:

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

(ve nadiren kullanılan birkaç tane daha, kabul edilen cevabı kontrol edin)

Bu res fonksiyonları çağrıldığında rota geri çağrısı geri dönmeyecektir. İşlevin sonuna veya bir return deyimine ulaşana kadar çalışmaya devam eder. Eğer bir yanıt gönderirken dönmek istiyorsanız bunu gibi işlemler yapabilir: return res.send().


Örneğin bu kodu ele alalım:

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

/ Api / route1 adresine bir POST isteği gönderildiğinde , geri aramadaki her satırı çalıştırır. A Üstbilgiler gönderildikten sonra ayarlanamaz çünkü res.json()iki kez çağrıldığı için iki mesaj gönderilir.

İstek başına yalnızca bir yanıt gönderilebilir!


Yukarıdaki kod örneğindeki hata açıktı. Daha tipik bir sorun, birkaç şubeniz olduğunda:

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

Geri arama ekli bu rota, veritabanında bir şirket bulur. Mevcut olmayan bir şirket için sorgu yaparken else ifşubeye girip 404 yanıt göndereceğiz. Bundan sonra, bir yanıt gönderen bir sonraki ifadeye devam edeceğiz. Şimdi iki yanıt gönderdik ve hata mesajı oluşacak. Bu kodu yalnızca bir yanıt gönderdiğimizden emin olarak düzeltebiliriz:

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

veya yanıt gönderildiğinde geri dönerek:

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

Büyük bir günahkar asenkron işlevlerdir. İşlevi bu sorudan alın, örneğin:

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

Burada findOneAndUpdate()kod örneğinde bir eşzamansız işlev ( ) var. Hiçbir hata yoksa ( err) findOneAndUpdate()çağrılacaktır. Bu işlev zaman uyumsuz olduğundan res.json(doc1)hemen çağrılır. Konumunda hiç hata olmadığını varsayalım findOneAndUpdate(). res.json(doc2)İçinde elsedaha sonra adı verilecek. Şimdi iki yanıt gönderildi ve Başlıklar ayarlanamıyor hata mesajı oluşuyor.

Düzeltme, bu durumda, kaldırmak olacaktır res.json(doc1). Her iki dokümanı istemciye geri göndermek için diğeri res.json()olarak yazılabilir res.json({ article: doc1, user: doc2 }).


2
Eşzamansız bir işlevin returnres.json
içindesiniz

Benim sorun res.senddöngü için kullanıyordu .
Maihan Nijat

1
Bu sonunda sorunu anlamak ve düzeltmek için bana yardımcı oldu, Çok teşekkürler :)
Pankaj Parkar

Zamanımı kurtardığın için çok teşekkür ederim.
Mohammad Faisal

Bu kesinlikle en iyi cevap!
Juanma Menendez

53

Ben de aynı sorunu vardı ve ben res.redirectbir returnaçıklama olmadan çağırıyordu , bu yüzden nextfonksiyon hemen sonra çağrıldı çünkü olduğunu fark ettim :

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

Hangisi olmalıydı:

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

43

Birçok kişi bu hatayı vurdu. Bu, zaman uyumsuz işlemeyle kafa karıştırıcı. Büyük olasılıkla kodunuzun bir kısmı ilk tıklamayla başlıkları ayarlıyor ve daha sonra gelecekteki bir tıklamayla zaman uyumsuz geri arama çalıştırıyorsunuz. Arada, yanıt üstbilgisi gönderilir, ancak daha sonra üstbilgiler (30X yönlendirmesi gibi) ek üstbilgiler eklemeye çalışır, ancak yanıt üstbilgisi zaten iletildiğinden çok geç.

Hatanızın nedenini tam olarak bilmiyorum, ancak araştırılacak potansiyel alanlar olarak geri aramalara bakın.

Kodunuzu basitleştirmek için kolay bir ipucu. Kurtul app.configure()ve sadece araapp.use doğrudan üst düzey kapsamınızda .

Ayrıca Facebook ve bir düzine kadar başka 3. taraf kimlik doğrulama sağlayıcısı yapan everyauth modülüne bakın .


30X yönlendirmesi bir HTTP yanıt kodudur. w3.org/Protocols/rfc2616/rfc2616-sec10.html 300-399 kodları farklı yönlendirme varyasyonlarıdır ve 302 ve 301 genellikle istemciyi alternatif bir URL'ye göndermek için kullanılır. Düğümde response.redirect (...) yaptığınızda, yanıtta 30X yönlendirme başlığı gönderilir.
Peter Lyons

3
Ohhhh. Arka arkaya 30 yönlendirmeyi hayal ediyordum
Janac Meena

17

Başımı bu konuda kaynattım ve geri aramalarla ilgili dikkatsiz bir hata nedeniyle oldu. İade edilmeyen geri aramalar, yanıtın iki kez ayarlanmasına neden olur.

Programım isteği doğrulayan ve DB sorgulayan bir kod vardı. hata varsa doğrulama sonra, doğrulama hataları ile index.js geri çağırıyordu. Doğrulama başarılı olursa devam eder ve db'yi başarı / başarısızlıkla vurur.

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

Olan şey şu: Incase validation geri arama alma ve yanıt alma başarısız. Ama geri dönmedi. Bu yüzden hala yöntem db gider ve başarı / başarısızlık vurmak devam ediyor. Aynı geri aramayı tekrar çağırır ve yanıtın iki kez ayarlanmasına neden olur.

Bu nedenle çözüm basittir, hata oluştuğunda yöntemin yürütülmeye devam etmemesi için geri çağrıyı 'döndürmeniz' ve böylece yanıt nesnesini bir kez ayarlamanız gerekir.

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

1
Teşekkürler! Bu da benim sorunum oldu. Sadece bir ctrl + f yaptı ve sonunda iki kez çağrılmasına neden oldu sonra bir callback(...)olmadan bulundu . return;res.send(...)

15

Yanıt gönderdikten sonra ifadeleri ilettiğinizde bu tür bir hata alırsınız.

Örneğin:

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

Gördüğünüz hatayla sonuçlanır, çünkü yanıt gönderildikten sonra aşağıdakiler res.sendyürütülmez.

Bir şey yapmak istiyorsanız, yanıtı göndermeden önce yapmalısınız.


Bu benim kesin
Joel Balmer

6

Bazen res.end veya res.send'den sonra next () işlevini çağırmayı denediğinizde , res.send veya res.end'den sonra next () varsa silmeyi deneyin. Not: here next (), istemciye yanıtınızla yanıt verdikten sonra ( örn. Res.send veya res.end ), yasal olmayacak şekilde tekrar yanıt vermek için bazı kodları yürütmeye çalıştığınız .

Misal :

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

next()Yukarıdaki fonksiyondan kaldırın ve çalışacaktır.


6

Geri arama işlevlerini kullanıyorsanız bloktan returnsonra kullanın err. Bu, hatanın meydana gelebileceği senaryolardan biridir.

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

Düğüm sürümü v10.16.0ve ekspres üzerinde test edilmiştir4.16.4


4

Bu hata, 2 yanıt gönderdiğinizde oluşur. Örneğin :

if(condition A)
{ 

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

}

if (condition B){

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

A ve B koşullarının herhangi bir nedenle doğru olup olmadığını düşünün, böylece ikinci olarak renderbu hatayı alırsınız


3

Benim durumumda soruna neden olan 304 yanıt (önbellek) oldu.

En kolay çözüm:

app.disable('etag');

Daha fazla kontrol istiyorsanız alternatif çözüm:

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


Benim durumumda da 304 yanıt. İşleme için Fiberler kullanıyorum. Herhangi bir şekilde cevabınız çok yardımcı olur. teşekkür ederim
Dileep stanley

Herkes etag üstbilgisini kaldırmak için ne anlama geldiğini açıklayabilir mi?
mattwilsn

2
ETag'ler sunucunun değişmemiş içerik göndermemesine izin verir. Kapatılması bu özelliği devre dışı bırakır. ETag wikipedia girişi ( en.wikipedia.org/wiki/HTTP_ETag ) daha geniş bir açıklamaya sahiptir.
16:25

3

Benim durumumda, React ve postal.js ile componentWillUnmountReact bileşenimin geri aramasındaki bir kanaldan çıkmadığım zaman oldu .


2

Buna gelen ve diğer çözümlerin hiçbiri yardımcı olmadı, benim durumumda bu, resim yüklemeyi işleyen ancak zaman aşımlarını işlemeyen bir rota üzerinde ortaya çıktı ve böylece yükleme çok uzun sürdü ve zaman aşımına uğradıysa, geri arama tetiklendiğinde zaman aşımı yanıtı gönderildikten sonra üstbilgiler zaman aşımını hesaba katmak üzere ayarlanmış olduğundan res.send () çağrılması kilitlenmeye neden oldu.

Bu, çok kısa bir zaman aşımı ayarlayarak ve rotayı makul büyüklükte bir görüntü ile vurarak kolayca yeniden üretildi, her seferinde çökme yeniden üretildi.


1
Bundan kaçınmak için zaman aşımını nasıl ele aldınız?

2

Sadece bunu eğdim. Yanıtları bu işlevden geçirebilirsiniz:

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

Bu middlware ekleyin ve işe yarayacak

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

Bu, istemciye yanıt verildiğinde ve yine yanıt vermeye çalıştığınızda olur. Kodunuzu, bir yere bu hataya neden olan istemciye yanıt döndürdüğünüzü kontrol etmelisiniz. Geri dönmek istediğinizde yanıtı kontrol edin ve bir kez gönderin.


1

Bu sözleri iç içe geçirirken bu sorunu yaşadım. Bir sözün içindeki bir söz, sunucuya 200 döndürür, ancak daha sonra dış sözün catch ifadesi 500 döndürür. Bunu düzelttiğimde sorun ortadan kalktı.


bunu tam olarak nasıl düzelttin? Vaatlerde de aynı sorun var. Onları iç içe kaçınamıyorum ... öyleyse nasıl iade beyanında yürütmeyi durdurmak?
saurabh

1

Buraya nuxt'tan geldi , sorun bileşenin asyncDatayöntemindeydi, returnhangi veri getirildiğini ve orada başlık ayarladığını vaat etmeyi unuttum .


1

Lütfen kodunuzun tek bir istek için birden fazla res.send () ifadesi döndürüp döndürmediğini kontrol edin. Bu sorunu yaşadığım gibi ....

Yeniden düzenleme düğümü uygulamamda bu sorun vardı. Hata şu ki

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

Break yazmadan anahtarı kullanarak çeşitli davaları ele alıyordu. Anahtar çantası ile az aşina olanlar için biliyorum, ara vermeden, anahtar kelimeleri iade. Durumdaki kod ve sonraki satırları ne olursa olsun yürütülür. Tek bir res.send göndermek istememe rağmen, bu hata nedeniyle, birden fazla res.send ifadesi döndürüyordu.

hata, istemciye gönderildikten sonra üstbilgileri ayarlayamaz. Bu, bunu ekleyerek veya return res.send (200) gibi her res.send () yönteminden önce return kullanarak çözüldü

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


ilhamın için teşekkürler bana da oldu. Durum varsa başka ile de çözdüm.
Amr AbdelRahman

1

Bu daha çok bir düğüm şeyidir,% 99'u iki kez geri aramanıza neden olur, ya da iki kez yanıt vermenize neden olur, ya da sonraki () iki kez vb. Benim sorunum bir döngü içinde next () kullanarak çözüldü. Next () öğesini döngüden kaldırın veya birden çok kez aramayı durdurun.



1

Sadece dönüş anahtar kelimesini şöyle ekliyorum: return res.redirect("/great");ve walla!


1

Firavun faresinin neden olduğu aynı problemi yaşadım.

düzeltme için etkinleştirmek gerektiğini Promisesekleyebilir, böylece: mongoose.Promise = global.Promisekullanılmasını sağlamaktadır kodunuzda, için native js promises.

bu soluma diğer alternatifler:

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

ve

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

ancak önce bu paketleri yüklemeniz gerekir.


1

bir RND'den sonra hata bulma:

1) hata kodum:

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

2) Başarı Kodum

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

fark, kullanılmış olmasıdır sendStatus () yerine durum () .


0

Typescript'te benim sorunum mesaj aldıktan sonra websocket bağlantısını kapatmamıştım.

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

0

Yukarıdan yardım almazsanız: noobs için Bu hatanın arkasındaki neden birkaç kez istek göndermektir, bazı durumlarda anlayalım: - 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();   
        }

`yukarıdaki next () çağrısında iki kez hata oluşacaktır

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

burada yanıt iki kez gönderiliyor, zaten bir yanıt gönderip göndermediğinizi kontrol edin


0

Benim durumumda birden fazla geri arama nedeniyle olur. next()Kod sırasında defalarca yöntem çağırdım


0

Benim sorunum yöntemi içinde olduğu setIntervalbir if/elseblok vardı, çalışan vardı :clearIntervalelse

      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Önce koymak if/elsehile yaptı.


0

Benim durumumda, bir döngüde, ben res.render()defalarca çağırmak için denenmiş olabilir.


-1

Bu hata durumunda tek yapmam gereken res.end () idi.

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

Karşılaşabileceğiniz diğer sorun res.json ve res'den sonra kod olmasıdır. yazmak. Bu durumda, bundan sonra yürütmeyi durdurmak için return komutunu kullanmanız gerekir.

 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 
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.