spróbować {} bez catch {} możliwe w JavaScript?


114

Mam wiele funkcji, które albo zwracają coś, albo generują błąd. W funkcji głównej wywołuję każdą z nich i chciałbym zwrócić wartość zwracaną przez każdą funkcję lub przejść do drugiej funkcji, jeśli pierwsza funkcja generuje błąd.

Więc w zasadzie to, co obecnie mam, to:

function testAll() {
    try { return func1(); } catch(e) {}
    try { return func2(); } catch(e) {} // If func1 throws error, try func2
    try { return func3(); } catch(e) {} // If func2 throws error, try func3
}

Ale tak naprawdę chciałbym tylko trygo zwrócić (tj. Jeśli nie zgłasza błędu). Nie potrzebuję catchbloku. Jednak kod taki jak try {}nie działa, ponieważ brakuje (nieużywanego) catch {}bloku.

Umieściłem przykład na jsFiddle .

Czy jest więc jakiś sposób, aby catchusunąć te bloki, osiągając ten sam efekt?

Odpowiedzi:


4

Nie. Musisz je zatrzymać.

Ma to sens, ponieważ błędów nie należy w ogóle ignorować po cichu.


16
W tym przypadku te funkcje nie powinny rzucać błędy, ale np powrotną nulli zrobić coś takiegoreturn func1() || func2() || func3();
ThiefMaster

53
Ta odpowiedź jest błędna w rzeczywistości, możesz mieć, try {}; finally {}jak pokazano na stackoverflow.com/a/5764505/68210
Daniel X Moore,

4
@DanielXMoore, bez catch (e) {}wyjątku zgłoszonego przez func1()uniemożliwiłoby func2()próbę.
binki

66
Czasami posiadanie pustego haczyka ma sens, więc nie zgadzam się z twoim argumentem.
Petr Peller

8
Ta odpowiedź jest błędna i myląca. „To właściwie ma sens”, mówisz, ale mylisz się, ma to sens tylko w niektórych przypadkach, w innych nie. To świetny przykład strasznej odpowiedzi, która została przyjęta w niewytłumaczalny sposób. Jest wiele przypadków, w których czasami nie ma bloku catch, jak w asyncfunkcji. Zmuszanie języka javascript do tworzenia pustych catchbloków jest oczywiście bezcelowe.
YungGun

236

Try bez catch klauzuli wysyła swój błąd do kolejnego wyższego połowu , lub w oknie, jeśli nie jest zdefiniowany w tym try catch.

Jeśli nie ma haczyk , wyrażenie try wymaga wreszcie klauzuli.

try {
    // whatever;
} finally {
    // always runs
}

Więc najlepszym sposobem byłoby napisanie czegoś takiego try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570

1
Powyższy komentarz nie odpowiada dokładnie OP, ponieważ nie chce on uruchomić funkcji 2, jeśli funkcja 1 się powiedzie.
Andrew Steitz,


Dziękuję, tego potrzebowałem :-) Byłoby naprawdę wspaniale, gdyby działało również bez try {} Mam na myśli: async () => {wskazujeWorkInProgress () await pipelineStep1 () await pipelineStep2 () ... w końcu {stopIndicator ( )}} Byłoby jasne, że chodzi o całą funkcję ;-) Te bloki prób są tam takie brzydkie ...
Lenny

35

Możliwe jest posiadanie pustego bloku catch, bez zmiennej błędu, zaczynając od ES2019 . Nazywa się to opcjonalnym chwytaniem i zostało zaimplementowane w V8 v6.6, wydanej w czerwcu 2018 r . Ta funkcja jest dostępna od Node 10 , Chrome 66 , Firefox 58 , Opera 53 i Safari 11.1 .

Składnia jest pokazana poniżej:

try {
  throw new Error("This won't show anything");
} catch { };

Nadal potrzebujesz catchbloku, ale może on być pusty i nie musisz przekazywać żadnej zmiennej. Jeśli w ogóle nie chcesz bloku catch, możesz użyć try/ finally, ale pamiętaj, że nie połknie on błędów, tak jak robi to pusty catch.

try {
  throw new Error("This WILL get logged");
} finally {
  console.log("This syntax does not swallow errors");
}


2
ta odpowiedź jest najbardziej aktualna! w zakresie polecenia wykonania 1. podejmuje próbę tryblokady. 2. Wyłapuje błąd. 3. Wykonuje finallyblok. 4. Zgłasza błąd. Czy to jest poprawne?
helsont

Dzięki @helsont. Jeśli chodzi o kolejność wykonania w drugim przykładzie kodu, nie jestem pewien, czy można stwierdzić, czy błąd został przechwycony i ponownie wyrzucony, czy po prostu (prawdopodobnie) po prostu wyrzucony i nie przechwycony w pierwszej kolejności (ponieważ nie ma catch). Otocz cały kod innym znakiem try/,catch a będziesz w stanie wyłapać This WILL get loggedbłąd.
Dan Dascalescu

Wygląda teraz bardzo czysto. Dzięki za udostępnienie!
LeOn - Han Li

10

Nie, catch(lub finally) jest tryprzyjacielem i zawsze tam jest w ramach próby / złapania .

Jednak jest całkowicie poprawne, aby były puste, jak w twoim przykładzie.

W komentarzach w twoim przykładowym kodzie ( jeśli func1 zgłasza błąd, spróbuj func2 ), wydawałoby się, że to, co naprawdę chcesz zrobić, to wywołać następną funkcję wewnątrz catchbloku poprzedniego.


1
Masz rację. Jednak jeśli kod podobny try {...}; try {...}byłby możliwy, znaczenie kodu może być jaśniejsze (spróbuj pierwszego, w przeciwnym razie spróbuj drugiego).
pimvdb

O twojej edycji: w przykładzie JSFiddle druga funkcja zwraca coś, więc czy trzecia funkcja jest naprawdę oceniana w tym przypadku? Myślałem, że returnstwierdzenie powstrzymuje cokolwiek po nim.
pimvdb

@pimvdb Przepraszamy, nie sprawdziłem skrzypiec. returnspowoduje przedwczesny powrót funkcji. Zaktualizuję swoją odpowiedź.
Alex

1
Ta odpowiedź jest błędna w rzeczywistości, możesz mieć, try {}; finally {}jak pokazano na stackoverflow.com/a/5764505/68210
Daniel X Moore,

1
@DanielXMoore Jasne, że tak, ale finally{}zasadniczo jest w tym samym duchu, co catch{}. Zaktualizuję odpowiedź.
Alex

6

Nie polecałbym try-last bez catch, ponieważ jeśli zarówno try block, jak i final block throw błędy, w moim własnym teście pojawia się błąd wyrzucony w klauzuli final, a błąd bloku try jest ignorowany:

try {
  console.log('about to error, guys!');
  throw new Error('eat me!');
} finally {
  console.log ('finally, who cares');
  throw new Error('finally error');
}

Wynik:

>     about to error, guys!
>     finally, who cares
>     .../error.js:9
>         throw new Error('finally error');
>         ^
>     
>     Error: finally error

1

Pasują do wszystkich języków, które znam (JavaScript, Java, C #, C ++). Nie rób tego.


1
Dziwne, że moja została odrzucona pięć lat później, kiedy mówi to samo, co inne odpowiedzi tutaj. Mój wydaje się być jedynym, który został odrzucony. Moderatorzy, proszę zwrócić uwagę.
duffymo

Tcl ma bardzo wygodną konstrukcję catch {my code}
jednowyrazową


Czemu? Czuje się bezużyteczny, chyba że spróbuje / w końcu.
duffymo

1

Postanowiłem spojrzeć na przedstawiony problem z innej perspektywy.

Udało mi się znaleźć sposób, aby dokładnie uwzględnić żądany wzorzec kodu, częściowo odnosząc się do nieobsługiwanego obiektu błędu wymienionego przez innego komentatora.

kod można zobaczyć @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch jest umieszczony w pętli for umożliwiającej wdzięczne opadanie. będąc w stanie iterować przez wszystkie potrzebne funkcje. gdy wymagana jest jawna obsługa błędów, używana jest dodatkowa tablica funkcji. nawet w przypadku tablicy błędów i funkcji z elementem obsługi błędów nie jest funkcją, błąd jest zrzucany do konsoli.

Zgodnie z wymaganiami stackoverflow tutaj kod jest wbudowany [edytowany tak, aby był zgodny z JSLint (usuń początkowe spacje w celu potwierdzenia), popraw czytelność]

function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }

// ctr = Code to Run <array>, values = values <array>, 
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
    "use strict";
    var cb; // cb = code block counter
    for (cb in ctr) {
        if (ctr.hasOwnProperty(cb)) {
            try {
                return ctr[cb](values[cb]);
            } catch (e) {
                if (typeof eh[cb] === "function") {
                    eh[cb](e);
                } else {
                    //error intentionally/accidentially ignored
                    console.log(e);
                }
            }
        }
    }
    return false;
}

window.alert(testAll([func1, func2, func3], [], []));

Wcześniejsze


1

Jeśli chcesz, aby funkcje 2 i 3 były uruchamiane w przypadku wystąpienia błędu, dlaczego nie umieszczasz ich w bloku catch?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}

0

Uważam, że musisz użyć funkcji pomocniczej, takiej jak:

function tryIt(fn, ...args) {
    try {
        return fn(...args);
    } catch {}
}

i używaj go jak:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.