Aşağıda, kod örneği ve seçilen blog yayınlarından alıntılar dahil olmak üzere bu konuyla ilgili birçok farklı kaynaktan bir özetleme ve küratörlük yer almaktadır. En iyi uygulamaların tam listesini burada bulabilirsiniz
Node.JS hata işlemenin en iyi uygulamaları
Sayı1: Zaman uyumsuz hata işleme için vaatler kullanın
TL; DR: Geri çağırma stilinde zaman uyumsuz hataları ele almak muhtemelen en hızlı cehennem yoludur (kıyamet piramidi). Kodunuza verebileceğiniz en iyi hediye, bunun yerine try-catch gibi çok kompakt ve tanıdık kod sözdizimi sağlayan saygın bir söz kitaplığı kullanmaktır
Aksi takdirde: Node.JS geri çağırma stili, işlev (err, yanıt), hata işleme ile sıradan kod, aşırı yuvalama ve garip kodlama kalıplarının karışımı nedeniyle sürdürülemez koda ulaşmanın umut verici bir yoludur
Kod örneği - iyi
doWork()
.then(doWork)
.then(doError)
.then(doWork)
.catch(errorHandler)
.then(verify);
kod örneği anti desen - geri arama stili hata işleme
getData(someParameter, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
getMoreData(a, function(err, result){
if(err != null)
//do something like calling the given callback function and pass the error
getMoreData(b, function(c){
getMoreData(d, function(e){
...
});
});
});
});
});
Blog alıntısı: "
Vaatlerle ilgili bir sorunumuz var" (Blog pouchdb'den "Düğüm Vaatleri" anahtar kelimeleri için 11. sırada yer aldı)
“… Ve aslında, geri aramalar daha uğursuz bir şey yapıyor: bizi programlama dillerinde genellikle verdiğimiz bir şeydir. . bunun için ulaşmak ve orada değil kadar, o ne kadar ihtiyacım farkında değiller sözlerin bütün mesele bize asenk gittiğinde Kaybettiğimiz dil temellerini geri vermektir. dönüşünü atmak ve yığın Ama onlardan yararlanmak için vaatlerin nasıl doğru kullanılacağını bilmek zorundayım. "
Sayı2: Yalnızca yerleşik Hata nesnesini kullanın
TL; DR: Hataları dize veya özel tür olarak atan kodu görmek oldukça yaygındır - bu hata işleme mantığını ve modüller arasındaki birlikte çalışabilirliği zorlaştırır. Node.JS yerleşik Error nesnesini kullanarak bir vaadi reddetmek, istisna atmak veya hata yaymak fark etmez tekdüzeliği artırır ve hata bilgilerinin kaybını önler
Aksi takdirde: Bazı modülleri yürütürken, hangi tür hataların geleceğinden emin olmamanız - gelen istisna hakkında mantık yürütmeyi ve onu ele almayı çok daha zorlaştırır. Buna değer olsa da, hataları tanımlamak için özel türler kullanmak yığın izlemesi gibi kritik hata bilgilerinin kaybolmasına neden olabilir!
Kod örneği - doğru yapmak
//throwing an Error from typical function, whether sync or async
if(!productToAdd)
throw new Error("How can I add new product when no value provided?");
//'throwing' an Error from EventEmitter
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
//'throwing' an Error from a Promise
return new promise(function (resolve, reject) {
DAL.getProduct(productToAdd.id).then((existingProduct) =>{
if(existingProduct != null)
return reject(new Error("Why fooling us and trying to add an existing product?"));
kod örneği anti desen
//throwing a String lacks any stack trace information and other important properties
if(!productToAdd)
throw ("How can I add new product when no value provided?");
Blog alıntısı: "Bir dize bir hata değildir"
(Blogdan, “Node.JS hata nesnesi” anahtar kelimeleri için 6. sırada yer aldı)
"… Hata yerine dize iletmek, modüller arasında birlikte çalışabilirliğin azalmasına neden olur. Hata denetimlerinin örneğini gerçekleştirebilecek veya hata hakkında daha fazla bilgi edinmek isteyen API'lerle sözleşmeleri keser . Göreceğimiz gibi hata nesnelerinin çok yapıcıya iletilen mesajı tutmanın yanı sıra modern JavaScript motorlarındaki ilginç özellikler .. "
Number3: Operasyonel ve programcı hatalarını ayırt etme
TL; DR: İşlem hataları (ör., API geçersiz bir girdi aldı), hata etkisinin tam olarak anlaşıldığı ve dikkatli bir şekilde ele alınabildiği bilinen durumları ifade eder. Öte yandan, programcı hatası (örn. Tanımsız değişkeni okumaya çalışmak) uygulamayı zarif bir şekilde yeniden başlatmayı dikte eden bilinmeyen kod hatalarını ifade eder
Aksi takdirde: Bir hata göründüğünde uygulamayı her zaman yeniden başlatabilirsiniz, ancak neden küçük ve tahmin edilen bir hata (işletim hatası) nedeniyle ~ 5000 çevrimiçi kullanıcıyı devre dışı bırakıyorsunuz? bunun tersi de ideal değildir - bilinmeyen bir sorun (programcı hatası) oluştuğunda uygulamayı yukarıda tutmak beklenmedik davranışlara yol açabilir. İkisini ayırmak taktiksel davranmayı ve verilen bağlama göre dengeli bir yaklaşım uygulamayı sağlar
Kod örneği - doğru yapmak
//throwing an Error from typical function, whether sync or async
if(!productToAdd)
throw new Error("How can I add new product when no value provided?");
//'throwing' an Error from EventEmitter
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
//'throwing' an Error from a Promise
return new promise(function (resolve, reject) {
DAL.getProduct(productToAdd.id).then((existingProduct) =>{
if(existingProduct != null)
return reject(new Error("Why fooling us and trying to add an existing product?"));
kod örneği - bir hatayı operasyonel (güvenilir) olarak işaretleme
//marking an error object as operational
var myError = new Error("How can I add new product when no value provided?");
myError.isOperational = true;
//or if you're using some centralized error factory (see other examples at the bullet "Use only the built-in Error object")
function appError(commonType, description, isOperational) {
Error.call(this);
Error.captureStackTrace(this);
this.commonType = commonType;
this.description = description;
this.isOperational = isOperational;
};
throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here what happened", true);
//error handling code within middleware
process.on('uncaughtException', function(error) {
if(!error.isOperational)
process.exit(1);
});
Blog Alıntı : "Aksi takdirde devlet risk" (Hata ayıklanabilir blog, "Node.JS yakalanmamış istisna" anahtar kelimeler için 3 sırada yer)
“ … JavaScript'te atmanın nasıl çalıştığının doğası gereği, referans sızıntısı yapmadan veya başka türlü tanımlanmamış kırılgan bir durum oluşturmadan“ kaldığınız yerden güvenli bir şekilde almak ”için neredeyse hiçbir yol yoktur. bir atılmış hata sürecini kapatmaya olduğunu . tabii ki, normal bir web sunucusuna, birçok bağlantıları açmak olabilir ve bir hata başkası tarafından tetiklenen çünkü aniden bu aşağı kapatmaya makul değildir. daha iyi bir yaklaşım olduğunu diğerlerinin normal zamanlarında bitmesine izin verirken hatayı tetikleyen isteğe bir hata yanıtı gönderin ve bu çalışandaki yeni istekleri dinlemeyi bırakın "
Sayı4: Merkezi yazılımın içinden, ancak ara katman yazılımı içinde olmayan hataları işleme
TL; DR: Postaya yönetici ve günlük kaydı gibi hata işleme mantığı, bir hata geldiğinde tüm uç noktaların (örn. Express ara katman yazılımı, cron işleri, birim sınama) çağırdığı özel ve merkezi bir nesnede kapsüllenmelidir.
Aksi takdirde: Hataların tek bir yerde ele alınmaması, kod çoğaltılmasına ve muhtemelen yanlış işlenen hatalara neden olur
Kod örneği - tipik bir hata akışı
//DAL layer, we don't handle errors here
DB.addDocument(newCustomer, (error, result) => {
if (error)
throw new Error("Great error explanation comes here", other useful parameters)
});
//API route code, we catch both sync and async errors and forward to the middleware
try {
customerService.addNew(req.body).then(function (result) {
res.status(200).json(result);
}).catch((error) => {
next(error)
});
}
catch (error) {
next(error);
}
//Error handling middleware, we delegate the handling to the centrzlied error handler
app.use(function (err, req, res, next) {
errorHandler.handleError(err).then((isOperationalError) => {
if (!isOperationalError)
next(err);
});
});
Blog alıntısı: "Bazen daha düşük düzeyler, hatayı arayanlarına yaymak dışında yararlı bir şey yapamaz" (Joyent blogundan, “Node.JS hata işleme” anahtar kelimeleri için 1 sırada yer aldı)
"… Aynı hatayı yığının çeşitli seviyelerinde halledebilirsiniz. Bu, daha düşük seviyeler hatayı arayanlara yaymak dışında yararlı bir şey yapamazsa, hatayı arayana yayar vb. yalnızca en üst düzey arayan uygun işlemin ne olduğunu bilir, bu işlemi yeniden denemek, kullanıcıya bir hata bildirmek veya başka bir şey rapor etmek anlamına gelir, ancak bu, tüm hataları tek bir üst seviyeye bildirmeye çalışmanız gerektiği anlamına gelmez. geri arama, çünkü bu geri aramanın kendisi hatanın hangi bağlamda oluştuğunu bilemez "
Number5: Swagger kullanarak belge API'si hataları
TL; DR: API arayanlarınıza hangi hataların karşılığında gelebileceğini bildirin, böylece bunları çökmeden düşünceli bir şekilde halledebilirler. Bu genellikle Swagger gibi REST API dokümantasyon çerçeveleri ile yapılır
Aksi takdirde: Bir API istemcisi yalnızca anlayamadığı bir hata aldığından çökmeye ve yeniden başlatmaya karar verebilir. Not: API'nizin arayanı siz olabilirsiniz (bir mikro hizmet ortamında çok tipiktir)
Blog alıntısı: "Arayanlara hangi hataların olabileceğini söylemelisiniz" (Joyent blogundan “Node.JS logging” anahtar kelimeleri için 1 sırada yer aldı)
… Hataları nasıl ele alacağımızdan bahsettik, ancak yeni bir işlev yazarken, işlevinizi çağıran koda nasıl hata iletiyorsunuz? … Hangi hataların meydana gelebileceğini bilmiyor veya ne anlama geldiğini bilmiyorsanız, programınız kaza dışında doğru olamaz. Dolayısıyla, yeni bir işlev yazıyorsanız, arayanlarınıza hangi hataların olabileceğini ve ne yaptıklarını söylemelisiniz
Sayı6: Bir yabancı kasabaya geldiğinde süreci nazikçe kapat
TL; DR: Bilinmeyen bir hata oluştuğunda (bir geliştirici hatası, bkz. En iyi uygulama numarası # 3) - uygulamanın sağlıklılığı konusunda belirsizlik var. Yaygın bir uygulama, Forever ve PM2 gibi bir 'yeniden başlatma' aracı kullanarak sürecin dikkatli bir şekilde yeniden başlatılmasını önerir.
Aksi takdirde: Bilmediğiniz bir istisna yakalandığında, bazı nesneler hatalı bir durumda olabilir (örneğin, küresel olarak kullanılan ve bazı dahili hatalardan dolayı olayları tetiklemeyen bir olay gönderici) ve gelecekteki tüm istekler başarısız olabilir veya çılgınca davranabilir
Kod örneği - kilitlenip kilitlenmeyeceğine karar verme
//deciding whether to crash when an uncaught exception arrives
//Assuming developers mark known operational errors with error.isOperational=true, read best practice #3
process.on('uncaughtException', function(error) {
errorManagement.handler.handleError(error);
if(!errorManagement.handler.isTrustedError(error))
process.exit(1)
});
//centralized error handler encapsulates error-handling related logic
function errorHandler(){
this.handleError = function (error) {
return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError);
}
this.isTrustedError = function(error)
{
return error.isOperational;
}
Blog alıntı: "Hata işleme hakkında üç düşünce okulu vardır" (Blog jsrecipes)
… Hata işleme ile ilgili başlıca üç düşünce okulu vardır: 1. Uygulamanın çökmesine izin verin ve yeniden başlatın. 2. Tüm olası hataları halledin ve asla kilitlenmeyin. 3. İkisi arasında dengeli yaklaşım
Number7: Hataların görünürlüğünü artırmak için olgun bir günlükçü kullanın
TL; DR: Winston, Bunyan veya Log4J gibi bir dizi olgun günlük oluşturma aracı hata bulma ve anlama işlemlerini hızlandıracak. Bu yüzden console.log'u unutun.
Aksi takdirde: console.logs üzerinden veya sorgulama araçları veya iyi bir günlük görüntüleyici olmadan dağınık metin dosyası aracılığıyla el ile gezinme sizi geç saatlere kadar meşgul tutabilir
Kod örneği - Winston günlükçüsü iş başında
//your centralized logger object
var logger = new winston.Logger({
level: 'info',
transports: [
new (winston.transports.Console)(),
new (winston.transports.File)({ filename: 'somefile.log' })
]
});
//custom code somewhere using the logger
logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', { anything: 'This is metadata' });
Blog alıntısı: "Bir günlükçü için birkaç gereksinimi tanımlayalım:" (Blogdan strongblog'dan)
… Birkaç gereksinimi tanımlayalım (bir günlükçü için): 1. Her günlük satırının zaman damgası. Bu oldukça açıklayıcıdır - her günlük girişinin ne zaman gerçekleştiğini söyleyebilmelisiniz. 2. Kayıt formatı, makineler ve insanlar tarafından kolayca sindirilebilir olmalıdır. 3. Birden fazla yapılandırılabilir hedef akışına izin verir. Örneğin, izleme günlüklerini bir dosyaya yazıyor olabilirsiniz, ancak bir hatayla karşılaştığınızda, aynı dosyaya yazın, ardından hata dosyasına yazın ve aynı anda e-posta gönderin…
Number8: APM ürünlerini kullanarak hataları ve kesinti süresini keşfedin
TL; DR: İzleme ve performans ürünleri (diğer adıyla APM) kod tabanınızı veya API'nızı proaktif olarak ölçer, böylece eksik olduğunuz hataları, çökmeleri ve yavaşladığınız parçaları otomatik olarak vurgulayabilir
Aksi takdirde: API performansını ve duruş sürelerini ölçmek için büyük çaba harcayabilirsiniz, muhtemelen gerçek dünya senaryosu altında en yavaş kod parçalarınızın hangileri olduğunu ve bunların UX'i nasıl etkilediğini asla bilemezsiniz.
Blog teklifi: "APM ürünleri segmentleri" (Yoni Goldberg blogundan)
"… APM ürünleri 3 ana bölümden oluşur: 1. Web sitesi veya API izleme - HTTP istekleri aracılığıyla çalışma süresini ve performansı sürekli olarak izleyen harici hizmetler. Birkaç dakika içinde kurulabilir. Aşağıda birkaç seçili yarışmacı bulunmaktadır: Pingdom, Uptime Robot ve New Relic
2 Kod enstrümantasyonu - yavaş kod tespiti, istisna istatistikleri, performans izleme ve daha birçok özellikten yararlanmak için uygulama içerisine bir ajan katmak isteyen ürünler ailesi.Aşağıdaki birkaç yarışmacı yarışmacıdır: New Relic, App Dynamics
3. Operasyonel zeka panosu -bu ürün yelpazesi, ops ekibini, uygulama performansında kolayca en üst düzeyde kalmanıza yardımcı olan metrikler ve küratörlü içerikle kolaylaştırmaya odaklanmıştır. Bu genellikle birden fazla bilgi kaynağının (uygulama günlükleri, DB günlükleri, sunucu günlüğü, vb.) Ve açık gösterge tablosu tasarım çalışmalarının toplanmasını içerir. Aşağıda birkaç yarışmacı seçilmiştir: Datadog, Splunk "
Yukarıdakiler kısaltılmış bir versiyondur - burada daha fazla en iyi uygulama ve örneklere bakın