Hata Nedir?
"Cannot set headers after they are sent to the client" hatası, HTTP yanıtı (response) başlıklarını (headers) bir kere gönderildikten sonra tekrar göndermeye çalıştığınızda ortaya çıkar. Express.js, bir HTTP yanıtını bir kere gönderdiğinde başlıklar sabitlenir. Yani, eğer bu yanıtı daha sonra değiştirmeye çalışırsanız, Express size bu hatayı verir.
- Yanıt gönderildikten sonra bir başka `res.send()`, `res.json()`, `res.redirect()` veya `res.end()` çağrısı yapılması.
- Asenkron fonksiyonlar veya callback'ler içinde iki defa yanıt gönderilmesi.
Bu Hata Nerede Çıkar?
Bu hatayı genellikle asenkron kodlarda görürsünüz. Örneğin, bir API isteği yaparken önce bir işlem bitmeden yanıt göndermeye çalışmak, bu hatayı tetikleyebilir.
```javascript
app.get('/api', (req, res) => {
setTimeout(() => {
res.send("Veri alındı");
}, 1000);
res.send("İlk Yanıt");
});
```
Burada gördüğünüz gibi, ilk `res.send("İlk Yanıt")` çağrısı hemen yapılır, ancak 1 saniye sonra başka bir `res.send("Veri alındı")` çağrısı yapılır. Bu da "Cannot set headers after they are sent to the client" hatasına neden olur.
Çözüm Yolları
1. Asenkron Kodları Düzgün Yönetmek
İlk olarak asenkron işlerinizi doğru bir şekilde yönetmelisiniz. `async/await` yapısını kullanarak yanıtları doğru bir sırayla göndermelisiniz.
app.get('/api', async (req, res) => {
try {
const data = await someAsyncFunction();
res.send(data);
} catch (err) {
res.status(500).send("Bir hata oluştu");
}
});
```
Burada, `async/await` kullanarak işlemi sırasıyla yönetiyor ve sadece bir kez `res.send()` çağrısı yapıyoruz. Böylece ikinci kez yanıt göndermenin önüne geçmiş oluyoruz.
2. Yanıtı Bir Kez Göndermek
`res.send()` veya `res.json()` çağrısını bir defa yapmaya dikkat edin. Eğer bir işlemde birden fazla yanıt göndermek gerekirse, program akışınızı dikkatlice kontrol etmelisiniz.
```javascript
let isSent = false;
app.get('/api', (req, res) => {
if (isSent) return; // Yanıt daha önce gönderildiyse, tekrar göndermiyoruz
res.send("Veri gönderildi");
isSent = true; // Yanıtı gönderdik, bir daha göndermeyeceğiz
});
```
Bu örnekte, `isSent` değişkeni ile yanıtın yalnızca bir kez gönderilmesini sağlıyoruz.
3. `return` Kullanmak
Eğer yanıtın tek seferde gönderilmesini sağlamak istiyorsanız, her yanıtın ardından `return` komutunu kullanmak faydalı olabilir.
```javascript
app.get('/api', (req, res) => {
if (someCondition) {
return res.send("Şart sağlanmadı");
}
res.send("Şart sağlandı");
});
```
Bu durumda, şart sağlanırsa ilk `res.send()` çağrısı yapılacak ve kodun geri kalanı çalışmayacak. Böylece birden fazla yanıt gönderilmesinin önüne geçilecektir.
Hata Ayıklarken Kullanabileceğiniz Araçlar
Hatanın sebebini bulmak bazen zor olabilir. Kodda farklı yerlerde `res.send()` veya `res.json()` çağrıları olabilir. Hangi çağrının hatayı oluşturduğunu bulmak için console.log() kullanabilirsiniz. Bu yöntem, hatayı izlemenizi kolaylaştırır.
app.get('/api', (req, res) => {
console.log("İlk Yanıt Gönderildi");
res.send("Veri alındı");
console.log("İkinci Yanıt Gönderilmeye Çalışılıyor");
res.send("Başka bir veri");
});
```
Bu şekilde, her bir yanıtın ne zaman gönderildiğini kolayca takip edebilir, hata noktalarını hızlıca bulabilirsiniz.