2013-08-23 26 views
5

'daki kullanım istisnaları Ekspresin oldukça basit bir yönü gibi göründüğü bir şeyin nasıl ele alınacağını anlamakta sorun yaşıyorum. Eşzamansız bir geriçağırımda bir istisna atabilen bir kodum varsa, bu istisnayı yakalayamamın bir yolu yoktur, çünkü try/catch bloğu artık geri arama çalıştırıldığı zaman kapsamda değildir. Bu senaryolarda, tarayıcı sonuçta sunucunun yanıt vermediğini belirten kadar beklemeye devam eder. Bu çok kötü bir kullanıcı deneyimi. Hemen müşteriye 500 hata verebilmeyi tercih ederim. Varsayılan ifade hatası işleyicisi, bu durumu ele almıyor. İşte bazı örnek kod: Yukarıdaki koddaEkspres

var express = require("express"); 

var app = express(); 
app.use(app.router); 
//express error handler (never called) 
app.use(function(err, req, res, next) { 
    console.log(err); 
    res.send(500); 
}); 

app.get("/test", function(req, res, next) { 
    require("fs").readFile("/some/file", function(err, data) { 
     a.b(); //blow up 
    }); 
}); 

app.listen(8888); 

, çizgi a.b(), bir "ReferenceError a tanımlanmadı" atar istisna. Tanımlanmış hata işleyici asla çağrılmaz. Dosya doğru okunduğundan bu durumda fs.readFile() tarafından döndürülen hata nesnesi null olduğuna dikkat edin. Hata, async işleyicinin içindeki koddur.

Node's uncaughtExpception kullanımı hakkında this post okundu, ancak the documentation bu yöntemi kullanmıyor. Kullanmış olsam bile, 500 cevabı kullanıcıya nasıl geri gönderirim? Ekspres yanıt nesnesi artık kullanmam için çevrede değil.

Peki bu senaryoyu nasıl ele alıyorsunuz?

+0

Neden hata, geri aramada atılır? Muhtemelen, MongooseObject içte bir hatayı, onu yakalayacağınız bir noktaya atıyor ve daha sonra geri çağırıyor (err). Şimdi yukarıda gösterilen geri dönüş bir yanıltıcı hata nesnesine sahiptir ve 500 yanıtı gönderebilirsiniz. – Plato

+0

Eğer Mongoose, bir hata ile geri aramıyorsa, duruma düşerse ... hmm Belki bir setTimeout sarıcı yapabilirdiniz. ama tüm hataların derhal geri çağrılmasını beklerdim – Plato

+0

Bu endişe duyduğum Mongoose değil, sadece bir uyumsuzluk işlevini çağırmak için bir yol olarak kullanıyordum. Kendi kodumun aptalca bir şey yapması ve bir istisnanın atılmasına neden olmasından endişeleniyorum. Bunu daha net hale getirmek için örnek kodu güncelleyeceğim. – d512

cevap

4

Tamam, ilk cevabımın bazı değerli bilgileri olduğundan, ancak konuyla ilgili konuların dışında olduğundan tamamen farklı bir yanıt göndereceğim.

Kısa yanıt: Yapılacak işlemin yapılması gereken en doğru şey: programınızın bir yığın izi yazdırması ve bir hata ile çıkması gerekir.

yatan düşünce:

Bu yüzden farklı kategoride hataları hakkında düşünmemiz gerekiyor. İlk cevabım, iyi yazılmış bir programın temiz bir şekilde ele alması ve ele alması gereken veri ile ilgili hatalarla ilgilidir. Tanımladığınız şey bir CRASH'tır. Bağlandığınız node.js belgelerini okursanız, doğrudur. Programınızın bu noktada yapabileceği tek yararlı şey, bir yığın izleme ile çıkıp bir süreç denetimcinin onu yeniden başlatmasına ve anlaşılmış bir duruma erişmesine izin verir. Programınız çöktükten sonra, yığının üstüne ulaşan bir istisnanın temel nedeni olabilecek son derece geniş hata aralığı nedeniyle esasen kurtarılamaz. Özel örneğinizde, bu hata, kaynak kodu hatası düzeltilinceye ve uygulama yeniden dağıtılana kadar her zaman devam edecektir. Test edilmemiş ve buggy kodunun uygulamanıza gireceğinden endişe ediyorsanız, daha fazla test edilmemiş ve buggy hata işleme kodunu eklemek doğru sorunu çözmüyor.

Ancak, hayır, bu istisnaya neden olan HTTP isteği nesnesine başvuruda bulunmanın bir yolu yoktur, bu nedenle AFAIK, tarayıcıda son kullanıcının algıladığı şekli değiştiremezsiniz. bir ham zaman aşımı konfigüre edebileceğiniz ve daha dostane bir hata sayfası gönderebileceğiniz ara tam tersi proxy katman (bu, tam bir HTML belgesi için olmayan herhangi bir talep için elbette işe yaramaz).

Dave Pacheco Düğüm

Error Handling in Node.js yılında Hata İşleme İncil'i Bence bu konuda kesin bir iştir. Kapsamlı, kapsamlı ve kapsamlı. Periyodik olarak okuma ve tekrar okuma yapmanızı tavsiye ederim. işlenmeyen bir özel durum kolaylıkla tekrarlanabilir veya yüksek frekans ile oluyor ise


, @ asparagino adlı çözmek için, bir kenar böyle değil, bu bir mikroptur. Yapılması gereken doğru şey, bu durum karşısında yakalanmamış istisnalar oluşturmamak için kodunuzu iyileştirmektir. Aslında bu durumu halledin, böylece bir programcı hatasını bir operasyonel hatayı dönüştürün ve programınız yeniden başlatma olmadan ve yakalanmamış bir istisna olmaksızın devam edebilir.

+0

Cevabınız için teşekkürler Peter. Okuduğum şeyden şüphe ettiğim şey buydu. Bir programın beklenmedik bir istisna karşısında yapabileceği tek yararlı şeyin yine de yeniden başlatılması olduğu düşüncesiyle% 100 katılıyorum. Açıkça son kullanıcı bakış açısından iyi bir deneyim değil. Buna ek olarak, o zamanda devam eden diğer tüm istekleri etkileyecektir. Üst düzey istisna işleyicileri kullanan ve 500'e geri dönen, hatayı günlüğe yazdıran, ancak hizmeti çalışır halde tutan çok sayıda web uygulaması yazdım. Her neyse, işe yarıyor, sadece onunla ilgilenmeliyim. Tekrar teşekkürler. – d512

+0

Evet, bunun çoğunlukla olay tabanlı IO'nun kaçınılmaz bir sonucu olduğunu düşünüyorum. JavaScript'in uber-dinamik yapısı da hataların üretime geçmesini kolaylaştırır. Belki diğer cevaplar bazı iyi önerilerle yüzleşecek. –

+3

@PeterLyons - Bir düğüm işlemi genellikle düzinelerce hatta binlerce eşzamanlı istekleri ele alır. Bunların her biri değerli veriler içerebilir ve tamamlanmadığı takdirde bir maliyet olacaktır. Bir hokkabaz yapıyorsun. Tüm topları, düştüğü anda düşürmeli mi? Hatalar ve özel durumlar günlüğe kaydedilmelidir. Günlükler gözden geçirilmeli, hatalar ve kenar koşulları izlenmeli ve sabitlenmelidir. Süreç bırakılmamalıdır. – asparagino

4

Express'in hata işleme aracını app.use(error, req, res, next) aracılığıyla kullanmalısınız. Express, normal ara katman yığını yakalanmamış bir istisna atarken kullandığı ayrı bir katmanı korur. (Yan not, sadece geri çağrının armonisini (beklenen argümanların sayısı), onu sıradan bir ara katman ya da hata işleme aracı yazılımı olarak kategorize etmek için birazcık büyüttüğüne bakar, bu yüzden sadece akılda tutulması gereken ifadeleri anlamanız gerekir. Bu, bir middleware işleme hatasıdır).

Sorunuza ve yorumlarınıza dayanarak, yalnızca istisna durumlarının node.js'de bu kadar yararlı olmadığını anlayın, çünkü her zaman uyumsuz çağrı yeni bir yığın alır, bu nedenle geri aramalar her yerde kullanılır ve 1. bağımsız değişken bir hata olarak evrenseldir . Örneğindeki try/catch10 bloğu, yalnızca findById tarafından atılan bir istisnayı yakalayacaktır (örneğin, id snippet'inizde olduğu gibi tanımlanmamışsa), ancak veritabanına gerçek bir çağrı yapıldığında, işte bu, çağrı yığını düğüm, async IO geri çağrısını çağırdığında tamamen farklı bir çağrı yığını başlayana kadar başka istisnalar gerçekleşmeyebilir.

Thanks for the answer, but this only works if I put the try/catch inside the async callback and have the catch do next(exp). I'd like to avoid having separate try/catch blocks in every single async callback.

Hayır, bu doğru değil. Manuel olarak next(exp) numaralı telefonu aramanız gerekmez. Express, hatayı yakalar ve sizin için hata işleme ara katmanını tetikler (bu ne demek ki, şu anda dev modda geliştirici dostu istisna rapor sayfalarıdır). Ve async kütüphaneleri, "normal" hata koşullarında bile istisnalar atmaz. Geri bildirime bir hata iletirler, bu nedenle genel olarak rahatsız etmek zorunda değilsiniz. Sadece geri arama işlevine iletilen bir hata parametresini göz ardı etmeyin, ve siz iyisiniz.

Sen düğümünde bu klişe görmüyorum:

someDb.query(someCriteria, function (error, result) { 
    try { 
    //some code to deal with result 
    } catch (exception) { 
    callback(exception); 
    } 
}); 

Gerçi bu görüyorsunuz:

someDb.query(someCriteria, function (error, result) { 
    if (error) { 
    callback(error); 
    return; 
    } 
    //some code to deal with result 
}); 

Düğüm farklı IO kolları, çağrı yığını anlamına gelen istisnalar anlamına gelen farklı çalışır Farklı çalışma, yani hata işleme farklı çalışır. Tek bir try/catch yazmadan çökmeden hataları yöneten kararlı bir node/express uygulaması yazabilirsiniz. (express, üst üste doğru ilerleyen yakalanmamış hataların üstesinden gelen bir tanesine sahiptir).İşlevsel bir sınırlama değil, yalnızca kodunuzu farklı yazmanız ve hataları istisnalar yerine geri aramalarla ele almanız gerektiği anlamına gelen async IO'nun bir öznesidir. Bunu, "olduğu gibi" bir "sınırlama" olarak düşünmek, gerçekten sadece bir teknik gerçeklik olan bir şey üzerinde olumsuz bir çağrışım koyuyor. Hem senkron hem de asenkronize paradigmada istisnai işlem için temiz ve sağlam modeller vardır.

+0

Cevabınız için teşekkürler, ancak bu yalnızca try/catch'u async callback'inin içine koyarsam ve catch'unu sonra yaparsa (exp) çalışırsa çalışır. Her bir async çağrısı için ayrı try/catch bloklarına sahip olmaktan kaçınmak isterim. – d512

+0

Evet, sanırım sorunu anlıyorum, bunun hakkında ne yapacağımı bilmiyorum. Bir noktada, kod bir istisna atar ve düğüm sürecinin çökmesini veya askıda kalmasını istemiyorum. Bu sadece düğümün doğal bir sınırlaması mı? – d512

+0

Peter, kapsamlı cevaplar göndermek için zaman ayırdığınız için teşekkürler. Sorunumu tam olarak açıklamıyorum ya da hata işleme kodumda yanlış bir şey yapıyorum. "Express, hatayı yakalayacak ve sizin için ara katman hatalarını tetikleyecektir" diyorsunuz, ancak bu işi yapamıyorum. Sorumu, gördüklerimi gösteren basit ancak eksiksiz bir örnek içermesi için yeniledim. – d512