Javascript try…catch…else…finally like Python, Java, Ruby, etc

后端 未结 5 843
别那么骄傲
别那么骄傲 2020-12-08 18:48

How can Javascript duplicate the four-part try-catch-else-finally execution model that other languages support?

A

相关标签:
5条回答
  • 2020-12-08 19:30

    Javascript does not have the syntax to support the no-exception scenario. The best workaround is nested try statements, similar to the "legacy" technique from 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();
    }
    

    Besides readability, the only problem is the success variable. If protected_code sets window.success = false, this will not work. A less readable but safer way uses a function namespace:

    // 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();
    }
    
    0 讨论(0)
  • 2020-12-08 19:31

    I know the question is old and answers has already given but I think that my answer is the simplest to get an "else" in javascripts try-catch-block.

    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*/
    }
    
    0 讨论(0)
  • 2020-12-08 19:33

    I know this is old, but here is a pure syntax solution, which I think is the proper way to go:

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

    The code in Protected-block is executed. If the code throws an error, Handler-block is executed; If no error is thrown, Else-block is executed.

    No matter what happened previously, Final-block is executed once the code block is complete and any thrown errors handled. Even if there’s an error in Handler-block or Else-block, the code in Final-block is still run.

    If an error is thrown in the Else-block it is not handled by the Handler-block but instead by the Else-handler-block

    And if you know that the Else-block will not throw:

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

    Moral of the story, don't be afraid to indent ;)

    Note: this works only if the Else-handler-block never throws.

    0 讨论(0)
  • 2020-12-08 19:38

    Extending the idea of jhs a little, the whole concept could be put inside a function, to provide even more readability:

    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();
      }
    };
    

    Then we can use it like this (very similar to the python way):

    try_catch_else_finally(function() {
      // protected block
    }, function() {
      // handler block
    }, function() {
      // else block
    }, function() {
      // final-block
    });
    
    0 讨论(0)
  • 2020-12-08 19:49

    Here's another solution if the problem is the common one of not wanting the error callback to be called if there is an uncaught error thrown by the first callback. ... i.e. conceptually you want ...

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

    But an error in the success cb causes the problem of cb getting called a second time. So instead I've started using

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

    which is a variant on @cbarrick's solution.

    0 讨论(0)
提交回复
热议问题