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.