javascript'te try-catch… bu iyi bir uygulama değil mi?


69

Javascript'te try-catch bloğu için bir hüküm var . Java veya başka bir dilde hata işlemesi zorunlu olmakla birlikte, bunları javascript'te daha fazla kullanan birini göremiyorum. İyi bir uygulama değil mi ya da sadece javascript'te onlara ihtiyacımız yok?


2
While in java or *any other language* it is mandatory to have error handling...- Pek sayılmaz. Java, evet, ama try-catch konusunda ısrar etmeyen birçok dil var (C # gibi).
Jim G.

Çünkü bunları zaman uyumsuz bir ortamda kullanamazsınız. Bunları sıklıkla kodları daha düşük soyutlama seviyelerinde senkronize ederek kullanırım, örneğin bir şeyi bir şeylere dönüştürerek, vb ...
inf3rno

Bahse girerim sunucu tarafı kodunda, istemci tarafı kodundan daha fazla deneme yakaladığını görürsün. Özel olduğun bilgi uç kodunun çoğu önemli bir şey yapmıyor. Boruyu KB'ye indirgeme üzerine bahis oynarım, çoğu uygulamada ve tarayıcı tarafı koşullarında, her hatadan kurtarmaktan daha önemlidir.
svidgen

Belki de kullanmaya çalışmaktan kaçınmanın başka bir yolu vardır ve ikisini de (monads) düğümde yazılmış bir web sıyırıcımız vardı. Bunu kullanarak tüm deneme yakalamaları kaldırdık.
kullanıcı93

Yanıtlar:


66

Biri throw, uygulamalarda hata koşullarını iletmenin bir yolu olarak hatalardan kaçınmalıdır .

throwİfadesi yalnızca "Bunun, kaza ve yanık asla İçin. Hiçbir şekilde zarif kurtarmak etmeyin" kullanılmalıdır

try catch ancak, ana bilgisayar nesnelerinin veya ECMAScript'in hata atabileceği durumlarda kullanılır.

Örnek:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

Öneriler node.js topluluğun ilk argüman olarak (yalnızca hatalar olmayan işlemler için meydana Çünkü) geri çağrıları etrafında hataları geçmesi olmasıdır

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

Try / catch gibi diğer konular da gerçekten pahalı ve çirkin ve sadece asenkronize işlemlerle çalışmıyor.

Bu nedenle, senkronize işlemler bir hata atmamalı ve senkronize olmayan işlemlerle çalışmadığından, hiç kimse ana bilgisayar nesneleri veya ECMAScript tarafından atılan hatalar haricinde catch kullanmaya çalışmamaktadır.


2
Kimsenin yakalamaya çalışamadığını söyleyecek kadar ileri gitmem , çoğu durumda iş için sadece yanlış bir araçtır. Gerçekten istisnai durumlar varsa, bir atmaya değer olabilir Error, ancak bunlar arasında çok az.
zzzzBov

7
@zzzzBov C durumu, çökmesi ve yanması için hata atmada yanlış bir şey yoktur. Sadece hataları yakalayıp kurtarman gerektiğini düşünmüyorum. Örneğin document.getElementById, öğe olmadığında atmaz, sadece geri döner null.
Aynısı

4
@Raynos, bir senkronizasyon fonksiyonundan fırlatma tamamen kabul edilebilir ve bu kullanım durumunda mantıklı. Geri çağırmaya hata döndürmek, atma hatası senkronize etmek gibi uyumsuzluk demektir.
sbartell

@Raynos, müşteri tarafında (Düğüm olmayan ortam) akış kontrolü için Hatalar / İstisnalar kullanmaktan kaçınılması konusunda herhangi bir tavsiyede bulundu mu? Bu yayını StackOverflow'ta buldum , ancak çoğunlukla Java'ya yönelik
Nisanda

@ b.long basit. hiç hata atma. Sorun çözüldü.
Raynos

32

Javascript'teki deneyin / yakalayın, Javascript'in zaman uyumsuz doğası nedeniyle diğer dillerde olduğu gibi kurşun geçirmez değildir. Bu pasajı göz önünde bulundurun:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

Sorun, kontrol akışının yürütülmeden tryönce bloktan ayrılmasıdır do_something_that_throws(), bu nedenle geri arama içine atılan hata asla yakalanmaz.

Bu nedenle, dene / yakala birçok durumda temel olarak uygunsuzdur ve bir şeyin zaman uyumsuz olarak kod çalıştırıp çalıştırmadığı her zaman açık değildir. Neyse ki, kendine özgü tek iş parçacıklı, asenkron geri çağırma deyimi ve gerçek kapanma desteği ile javascript zarif bir alternatif sunar: devam eden stil hatası işleme. Bir fonksiyon olarak herhangi bir hataya doğru cevabı iletmeniz yeterli, örneğin:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);

5
diğer dillerde de kurşun geçirmez değildir. Bu kodu, zaman uyumsuz geri aramaları destekleyen herhangi bir dile aktarın;
Raynos,

2
@Raynos: Haklısın; Bununla birlikte, diğer diller (veya destekleyici kültürleri) bunu Javascript'in yaptığı gibi asenkron geri çağırma deyimine çok fazla almazlar ve çoğu diğer ortamın çok iş parçacıklı doğası nedeniyle, denemenin / yakalamanın eksiklikleri daha belirgindir ve birçok ihtarla çevrili olan insanlar, çok dişli / asenkron geri çağırma durumlarında doğal olarak dikkatli bir şekilde basarlar ve potansiyel tehlikelerin daha farkındadırlar.
tdammers

Bu gerçekten JavaScript’in “asenkron doğası” nedeniyle mi? Görebildiğim kadarıyla, Try / Catch teorik olarak tanımlayıcıların sözlü olarak nasıl kapandığı gibi sözcüksel olarak çalışabilir; sadece JavaScript’te bu şekilde çalışmaz.
Brian Gordon

2
Node.js> = 0.8’de, asenkron olarak denemenin / yakalamanın mümkün olduğunu belirtmeye değer, lütfen benim soruma bakın benim stackoverflow.com/questions/14301839/…
Benjamin Gruenbaum

Eşzamanlı deneme yakalamaya alternatif olan tek seçenek, zaman uyumsuz devam eden geçiş stili midir?
CMCDragonkai

23

Bu cevaplar bir sürü biraz eski ve hesaba yeni ES7 özelliklerini yapmayız asyncve await.

Kullanılması async/ awaitistediğiniz gibi asenkron kontrol akışını almak şimdi edebilirsiniz:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: 'noreply@domain.com`, subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

Burada async/await hakkında daha fazla bilgi edinin . Babil kullanarak async/ awaitşimdi kullanabilirsiniz .


Ancak senkron koduna benzer
Atul Agrawal

@AtulAgrawal evet, mesele bu. Eşzamansız / beklemede, eşzamanlı olmayan bir tarzda eşzamansız kod yazmanıza olanak tanır, böylece "geri çağırma cehenneminden" kaçın ve birlikte birçok vaadi zincirlemekten kaçınabilirsiniz. Benim düşünceme göre zaman uyumsuz kod yazmak için çok eğlenceli bir yol
Dana Woodman

peki zaman uyumsuz kod yapıyorsak javascript kullanmanın faydası nedir? çünkü insanların çoğu, zaman uyumsuz olmaları nedeniyle javascript kullanmaktadır
Atul Agrawal

2
@AtulAgrawal, her iki dünyanın da en iyisini elde edersiniz - dilin async doğasından zevk alırsınız (yukarıdaki kod hala async olarak çalıştırılır - ipliği ve herkesi serbest bırakır) ve daha programcı dostu bir kodlama stilinin avantajlarından yararlanın. Olsa da, sorun değil ...
ZenMaster

15

javascript'teki try-catch, bunları uygulayan diğer dillerdeki kadar geçerli ve faydalıdır. Javascript'te diğer dillerde olduğu kadar kullanılmamasının büyük bir nedeni var. Aynı javascript çirkin bir betik dili olarak görülüyor, insanların javascript programcılarının gerçek programcılar olmadığını düşünmelerinin sebebi aynı:

  • Javascript inanılmaz derecede erişilebilir ve yaygın bir dildir.

Pek çok insanın javascript'e (tarayıcıların desteklediği tek dil sayesinde) maruz kalmanın tek nedeni, orada pek çok profesyonelce kodunuz olduğu anlamına gelir. Tabii ki birçok küçük sebep var:

  • javascript'teki bazı şeyler eşzamansızdır ve bu nedenle kullanılamaz catch(eşzamanlı olmayan şeyler)
  • Try-catch'in büyük bir performansa sahip olduğu hakkında çok fazla abartılı konuşma yapıldı. It has bir performans isabet biraz , ama çoğu kod, buna değer.
  • javascript (maalesef) hataları sessizce görmezden gelecek şekilde uygulandı (örneğin dizeleri otomatik olarak sayılara çevirir)

Ne olursa olsun, try-catch gerekir kullanılabilir, ancak tabii ki gerekir bunları düzgün kullanmayı öğrenmek - programlamada her şey gibi.


3
Ve neden hiç aşağı oy kullanmadın, oh sessiz aşağı oy verdin?
user250878

Kabul. Kabul edilen cevabın genel olarak doğru olduğunu düşünüyorum, ancak yerel nesnelerle uğraşmaktan başka, try-catch kullanmak ve hatta atmak için iyi nedenler var. Bir geri aramaya geçmek yerine bir hata atıldığında, daha fazla işlemi durdurur ve yığını üstesinden kaldırabileceğinden ilk bloğa atlar. Bu, büyük bir avantajdır ve senkronize işlemler için, özellikle derin yuvalamalar içeriyorsa, mükemmel bir anlam ifade eder. İstisnaların "kötü" olduğunu söylemek delice görünüyor (açık nedenlerden başka hariç) - aslında benzersiz bir "gücü" olan çok faydalı bir araç.
Noktalı virgül

2
JQuery'in kaynak kodunu okumak için zaman ayırdınız mı? Kabul edilen cevabında belirtilen senaryolar dışında, orada neredeyse hiç deneme yapılmadı: hata veren yerel / ana bilgisayar nesnelerini özellik tespit etmek ve kullanmak. Try-catch fazla kullanmayan kodları çağırmak (jQuery gibi) 'profesyonelce' aptalca görünüyor. Dürüst olmak gerekirse, özellikle Java'dan gelen ve try-catch gibi dil özelliklerini kullanma eğiliminde olan yeni Javascript programcılarının olduğunu düşünüyorum.
Stijn de Witt

6

try..catchJavaScript'te nadir görülen bir nedenin , dilin hataya oldukça tolerans gösterdiğine inanıyorum . Durumların büyük çoğunluğu kod kontrolleri, iyi varsayılanlar ve zaman uyumsuz olaylar kullanılarak ele alınabilir. Bazı durumlarda, yalnızca bir desen kullanmak sorunları önler:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

İstisnaların ortaya çıkmasına neden olan diğer dillerdeki bazı önemli konular JS'de yoktur. Tip döküm, zamanın büyük çoğunluğuna ihtiyaç duymaz. Bunun yerine, tercih edilen yöntem tipik olarak kontrol özelliğidir (belirli bir arayüzü zorlamak):

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

Dilin async/ eklenmesiyle daha yaygın hale geliyor. Eşzamansız formu olduğu vaat ediyor, birinin beklemesi gerekenleri anlamlandırıyor:awaittry..catchtry..catch

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

bunun yerine şöyle yazılmalı:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}

3

Muhtemelen başka bir sebep denemek / yakalamak Javascript'te çok fazla kullanılmaması, konstrüksiyonun Javascript'in ilk sürümlerinde mevcut olmamasıydı ... daha sonra eklendi.

Sonuç olarak, bazı eski tarayıcılar desteklemiyor. (Aslında, bazı eski tarayıcılarda ayrıştırıcı / sözdizimi hatasına neden olabilir; bu, diğer birçok hata türünden daha "savunmacı bir şekilde programlanması" zor olan bir şeydir.)

Daha önemlisi, başlangıçta mevcut olmadığından, başlangıçta piyasaya sürülen Javascript yerleşik işlevler (çoğu dilde "kütüphane" işlevlerine ne denir) bunu kullanmaz. (Eğer "atma" yapmazsa, someobject.somefunction () 'dan bir hatayı "yakalamak" çok işe yaramaz, ancak bir sorunla karşılaştığında "null" döndürür.)


Yine bir başka olası neden, deneme / yakalama mekanizmasının başlangıçta gerekli görünmediğidir (ve yine de bu kadar faydalı görünmüyor). Sadece çağrılar rutin olarak birkaç seviye derinlere yerleştirildiğinde gerçekten ihtiyaç duyulur; sadece bir tür ERRNO döndürmek doğrudan aramalar için iyi sonuç verir (her ne zaman mümkün olduğunda onu gerçekten faydalı kılmakla birlikte, çoğu dilde en iyi uygulama onu derinden yerleştirilmiş aramalar yerine her yerde kullanmaktır ). Javascript mantığının başlangıçta küçük ve basit olması beklendiğinden (sonuçta, sadece bir web sayfasına eklenmiştir :-), işlev çağrılarının derinden iç içe olması beklenmiyordu ve bu nedenle bir deneme / yakalama mekanizması gerekli gözükmüyordu.


3
Hayır hayır hayır, kesinlikle böyle değil. Eskilerin motorları uzun süre boyunca artık önemli değil ve genel olarak javascript topluluğu, gerekçelendirildiğinde eski şeyleri bırakmakta hızlıdır. Javascript geliştiricilerinin çoğunun şimdi IE6 sonrası olduklarına bile bahse girerim.
Camilo Martin

0

Bu kadar kullanılmadıklarına inanıyorum çünkü Javascript istemcisi yan kodunda istisnalar atmak bir sayfanın hata ayıklamasını zorlaştırıyor.

Aksine durumlar atma yerine, genellikle el uyarı kutusu göstermeyi tercih, (yani alert("Error, invalid...");)

Garip gelebilir, ancak müşteriler kendi oluşturduğunuz bir sayfayı kullanıyorsa ve sayfa bir istisna atarsa, müşteri bir teknoloji meraklısı kodlayıcı olmadıkça , hiçbir zaman söyleyemeyeceği bir Javascript hataları müşteri tarafında gerçekleşir. sorun ne?

Sizi yalnızca “Hey, sayfa X çalışmıyor!” Diyerek sizi arayacak ve neyin yanlış gittiğini ve kodun neresinde olduğunu bulmak tamamen size bağlı olacaktır.

Uyarı kutusunu kullanmak yerine, arayıp şöyle bir şeyi söylemesi daha muhtemeldir: "Hey, sayfa X butonuna tıkladığımda ... yazan bir kutu gösterir ..." , güven bana, bulması çok daha kolay olacak böcek.

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.