web-dev-qa-db-ja.com

Javascript try ... catch ... else ...最終的にPython、Java、Rubyなどのように

Javascriptは、他の言語がサポートする4つの部分からなるtry-catch-else-finally実行モデルをどのように複製できますか?

明確で簡潔な要約は Python 2.5の新機能 からです。 Javascriptの用語で:

// XXX THIS EXAMPLE IS A SYNTAX ERROR
try {
  // Protected-block
} catch(e) {
  // Handler-block
} else {
  // Else-block
} finally {
  // Final-block
}

Protected-blockのコードが実行されます。コードが例外をスローした場合、Handler-blockが実行されます。例外がスローされない場合、Else-blockが実行されます。

以前に何が起こったとしても、コードブロックが完了し、スローされた例外が処理されると、Final-blockが実行されます。 Handler-blockまたはElse-blockにエラーがあり、新しい例外が発生した場合でも、Final-blockのコードは実行されます。 。

Else-blockを切り取ってProtected-blockの最後に貼り付けるのは間違っていることに注意してください。 Else-blockでエラーが発生した場合、Handler-blockで処理してはなりません

35
JasonSmith

Jhsの概念を少し拡張すると、概念全体を関数内に配置して、さらに読みやすくすることができます。

var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) {
  try {
    var success = true;
    try {
      protected_code();
    } catch(e) {
      success = false;
      handler_code({"exception_was": e});
    }
    if(success) {
      else_code();
    }
  } finally {
    finally_code();
  }
};

次に、次のように使用できます(pythonの方法と非常によく似ています):

try_catch_else_finally(function() {
  // protected block
}, function() {
  // handler block
}, function() {
  // else block
}, function() {
  // final-block
});
27
Jakob

私はこれが古いことを知っていますが、ここに純粋な構文ソリューションがあります。これが適切な方法だと思います。

try {
    // Protected-block
    try {
        // Else-block
    } catch (e) {
        // Else-handler-block
    }
} catch(e) {
    // Handler-block
} finally {
    // Final-block
}

Protected-blockのコードが実行されます。コードがエラーをスローした場合、Handler-blockが実行されます。エラーがスローされない場合、Else-blockが実行されます。

以前に何が起こったとしても、コードブロックが完了し、スローされたエラーが処理されると、Final-blockが実行されます。 Handler-blockまたはElse-blockにエラーがあったとしても、Final-blockのコードは実行されます。

Else-blockでエラーがスローされた場合、Handler-blockによって処理されますnot =しかし代わりにElse-handler-block

そして、Else-blockがスローされないことがわかっている場合:

try {
    // Protected-block
    // Else-block
} catch(e) {
    // Handler-block
} finally {
    // Final-block
}

話の教訓、インデントすることを恐れないでください;)

注:これは、Else-handler-blockがスローされない場合にのみ機能します。

33
cbarrick

Javascriptには、例外なしのシナリオをサポートする構文がありません。最善の回避策は、ネストされたtryステートメントです。これは、 PEP 341 の「レガシー」手法に似ています。

// A pretty-good try/catch/else/finally implementation.
try {
  var success = true;
  try {
    protected_code();
  } catch(e) {
    success = false;
    handler_code({"exception_was": e});
  }
  if(success) {
    else_code();
  }
} finally {
  this_always_runs();
}

読みやすさに加えて、唯一の問題はsuccess変数です。 protected_codewindow.success = falseを設定する場合、これは機能しません。読みにくく、安全な方法は、関数の名前空間を使用します。

// A try/catch/else/finally implementation without changing variable bindings.
try {
  (function() {
    var success = true;
    try {
      protected_code();
    } catch(e) {
      success = false;
      handler_code({"exception_was": e});
    }
    if(success) {
      else_code();
    }
  })();
} finally {
  this_always_runs();
}
8
JasonSmith

私は質問が古く、答えがすでに与えられていることを知っていますが、私の答えはjavascriptstry-catch-blockで「else」を取得するのが最も簡単だと思います。

var error = null;
try {
    /*Protected-block*/
} catch ( catchedError ) {
    error = catchedError; //necessary to make it available in finally-block
} finally {
    if ( error ) {
        /*Handler-block*/
        /*e.g. console.log( 'error: ' + error.message );*/
    } else {
        /*Else-block*/
    }
    /*Final-block*/
}
6
jaheraho

問題が、最初のコールバックによってスローされたキャッチされていないエラーがある場合にエラーコールバックが呼び出されたくないという一般的な問題である場合、別の解決策があります。 ...つまり、概念的には...

try { 
    //do block 
    cb(null, result);
} catch(err) {
    // err report
    cb(err)
}

しかし、成功したcbでエラーが発生すると、cbが2回呼び出されるという問題が発生します。だから代わりに私は使い始めました

try { 
    //do block 
    try { 
        cb(null, result); 
    } catch(err) { 
        // report uncaught error 
    }
} catch(err) {
    // err report
    cb(err)
}

これは@cbarrickのソリューションの変形です。

0
Mitra Ardron