tentar {} sem travar {} é possível em JavaScript?

114

Tenho várias funções que retornam algo ou geram um erro. Em uma função principal, eu chamo cada uma delas e gostaria de retornar o valor retornado por cada função ou ir para a segunda função se a primeira função gerar um erro.

Basicamente, o que tenho atualmente é:

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
}

Mas, na verdade, gostaria apenas tryde devolvê-lo (ou seja, se não gerar um erro). Eu não preciso do catchbloco. No entanto, o código try {}falha porque falta um catch {}bloco (não utilizado) .

Eu coloquei um exemplo no jsFiddle .

Então, há alguma maneira de catchremover esses bloqueios e, ao mesmo tempo, obter o mesmo efeito?

pimvdb
fonte

Respostas:

4

Não. Você tem que mantê-los.

Na verdade, isso faz sentido, pois os erros não devem ser ignorados silenciosamente.

ThiefMaster
fonte
16
Nesse caso, essas funções não devem nullreturn func1() || func2() || func3();
gerar
53
Esta resposta é factualmente incorreta, você pode ver try {}; finally {}como mostrado em stackoverflow.com/a/5764505/68210
Daniel X Moore
4
@DanielXMoore, sem o catch (e) {}, a exceção lançada por func1()impediria func2()de ser tentado.
binki,
66
Às vezes, faz todo o sentido ter uma captura vazia, então não concordo com seu argumento.
Petr Peller
8
Essa resposta é factualmente incorreta e enganosa. “Na verdade faz sentido” você diz, mas você está errado, só faz sentido em alguns casos e não em outros. É um ótimo exemplo de uma resposta terrível sendo aceita inexplicavelmente. Existem muitos casos em que faz sentido não ter bloco catch, como em uma asyncfunção, às vezes. Ser forçado pela linguagem javascript a criar catchblocos vazios é claramente inútil.
YungGun
236

Um try sem uma cláusula catch envia seu erro para o próximo catch superior , ou janela, se não houver catch definido dentro desse try.

Se você não tiver um catch , uma expressão try requer uma cláusula finally .

try {
    // whatever;
} finally {
    // always runs
}
kennebec
fonte
Então, a melhor maneira seria escrever algo como try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570
1
O comentário acima não responde OP com precisão porque ele não deseja executar a função 2 se a função 1 for bem-sucedida.
Andrew Steitz
2
Observe que uma tentativa sem travar não engole erros .
Dan Dascalescu 01 de
Obrigado, é o que eu precisava :-) Seria realmente incrível se ele também funcionasse sem o teste {} Quero dizer: async () => {indicWorkInProgress () await pipelineStep1 () await pipelineStep2 () ... finally {stopIndicator ( )}} Seria claro que toda a função se destina ;-) Esses blocos try são tão feios aí ...
Lenny
35

É possível ter um bloco catch vazio, sem uma variável de erro, começando com ES2019 . Isso é chamado de vinculação de captura opcional e foi implementado no V8 v6.6, lançado em junho de 2018 . O recurso está disponível desde o Node 10 , Chrome 66 , Firefox 58 , Opera 53 e Safari 11.1 .

A sintaxe é mostrada abaixo:

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

Você ainda precisa de um catchbloco, mas pode estar vazio e você não precisa passar nenhuma variável. Se você não quiser um bloco catch, você pode usar try/ finally, mas observe que ele não engole erros como um catch vazio faz.

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

Dan Dascalescu
fonte
2
esta resposta é a mais atualizada! em termos de ordem de execução, 1. tenta o trybloqueio. 2. Identifica o erro. 3. Executa o finallybloco. 4. Lança o erro. Isso está correto?
helsont
Obrigado @helsont. Quanto à ordem de execução no segundo exemplo de código, não tenho certeza se alguém pode dizer se o erro foi detectado e relançado ou apenas (provavelmente) simplesmente acionado e não detectado em primeiro lugar (já que não há catch). Cerque todo o código com outro try/catch e você poderá detectar o This WILL get loggederro.
Dan Dascalescu
Parece muito limpo agora. Obrigado por compartilhar!
LeOn - Han Li
10

Não, catch(ou finally) é tryamigo de e sempre está lá como parte do try / catch .

No entanto, é perfeitamente válido tê-los vazios, como no seu exemplo.

Nos comentários em seu código de exemplo ( se func1 gerar erro, tente func2 ), parece que o que você realmente deseja fazer é chamar a próxima função dentro do catchbloco anterior.

alex
fonte
1
Você está certo. No entanto, se o código como try {...}; try {...}for possível, o significado do código pode ser mais claro (tente o primeiro, caso contrário, tente o segundo).
pimvdb
Sobre sua edição: No exemplo JSFiddle, a segunda função retorna algo, então a terceira função é realmente avaliada nesse caso? Achei que uma returndeclaração impede qualquer coisa que venha depois dela.
pimvdb
@pimvdb Desculpe, não verifiquei o violino. returnfará com que a função retorne prematuramente. Vou atualizar minha resposta.
alex
1
Esta resposta é factualmente incorreta, você pode ver try {}; finally {}como mostrado em stackoverflow.com/a/5764505/68210
Daniel X Moore
1
@DanielXMoore Claro, é, mas finally{}basicamente tem o mesmo espírito que catch{}. Vou atualizar a resposta.
alex
6

Eu não recomendaria try-finally sem catch, porque se o bloco try e o bloco finally gerassem erros, o erro lançado na cláusula finally seria gerado e o erro do bloco try seria ignorado, em meu próprio teste:

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

Resultado:

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

Eles vão juntos em todas as linguagens que eu conheço que os possuem (JavaScript, Java, C #, C ++). Não faça isso.

duffymo
fonte
1
Estranho que a minha foi rejeitada cinco anos depois, quando diz a mesma coisa que outras respostas aqui. O meu parece ser o único que teve uma votação negativa. Moderadores, por favor, tomem nota.
duffymo
Tcl tem uma construção de palavra única muito convenientecatch {my code}
MKaama
Por quê? Parece inútil, a menos que seja tentar / finalmente.
duffymo 01 de
1

Decidi olhar para o problema apresentado de um ângulo diferente.

Consegui determinar uma maneira de permitir o padrão de código solicitado enquanto, em parte, aborda o objeto de erro não tratado listado por outro comentador.

o código pode ser visto em http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch é colocado dentro de um loop for permitindo uma queda elegante. enquanto é capaz de iterar por meio de todas as funções necessárias. quando o tratamento explícito de erros é necessário, uma matriz de função adicional é usada. no caso de erro e array funcional com o elemento manipuladores de erro não é uma função, o erro é despejado no console.

De acordo com os requisitos de stackoverflow, aqui está o código embutido [editado para tornar compatível com JSLint (remover espaços iniciais para confirmar), melhorar a legibilidade]

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], [], []));

user1800957
fonte
1

Se você deseja que as funções 2 e 3 sejam acionadas apenas se ocorrer um erro, por que você não as está colocando no bloco catch?

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

Eu acredito que você precisa usar a função auxiliar como:

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

e usá-lo como:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
Itay Merchav
fonte
-2

Desde ES2019 você pode usar facilmente try {}sem catch {}:

try {
  parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}

Para mais informações, consulte a proposta de Michael Ficcara

JamesJGoodwin
fonte
1
Não, catchainda é obrigatório, é apenas a ligação que não é necessária ...
chipit24