Handling specific errors in JavaScript (think exceptions)

前端 未结 6 1741
醉梦人生
醉梦人生 2020-12-02 11:28

How would you implement different types of errors, so you\'d be able to catch specific ones and let others bubble up..?

One way to achieve this is to modify the

相关标签:
6条回答
  • 2020-12-02 12:14

    As noted in the comments below this is Mozilla specific, but you can use 'conditional catch' blocks. e.g.:

    try {
      ...
      throwSpecificError();
      ...
    }
    catch (e if e.sender === "specific") {
      specificHandler(e);
    }
    catch (e if e.sender === "unspecific") {
      unspecificHandler(e);
    }
    catch (e) {
      // don't know what to do
      throw e;
    } 
    

    This gives something more akin to typed exception handling used in Java, at least syntactically.

    0 讨论(0)
  • 2020-12-02 12:17

    Module for export usage

    /**
     * Custom InputError
     */
    class InputError extends Error {
      /**
       * Create InputError
       * @param {String} message
       */
      constructor(message) {
        super(message);
        this.name = this.constructor.name;
        Error.captureStackTrace(this, this.constructor);
      }
    }
    
    /**
     * Custom AuthError
     */
    class AuthError extends Error {
      /**
       * Create AuthError
       * @param {String} message
       */
      constructor(message) {
        super(message);
        this.name = this.constructor.name;
        Error.captureStackTrace(this, this.constructor);
      }
    }
    
    /**
     * Custom NotFoundError
     */
    class NotFoundError extends Error {
      /**
       * Create NotFoundError
       * @param {String} message
       */
      constructor(message) {
        super(message);
        this.name = this.constructor.name;
        Error.captureStackTrace(this, this.constructor);
      }
    }
    
    module.exports = {
      InputError: InputError,
      AuthError: AuthError,
      NotFoundError: NotFoundError
    };
    

    Import into script:

    const {InputError, AuthError, NotFoundError} = require(path.join(process.cwd(), 'lib', 'errors'));
    

    Use:

    function doTheCheck = () =>
      checkInputData().then(() => {
        return Promise.resolve();
      }).catch(err => {
        return Promise.reject(new InputError(err));
      });
    };
    

    Calling code external:

    doTheCheck.then(() => {
      res.send('Ok');
    }).catch(err => {
      if (err instanceof NotFoundError) {
        res.status(404).send('Not found');
      } else if (err instanceof AuthError) {
        res.status(301).send('Not allowed');
      } else if (err instanceof InputError) {
        res.status(400).send('Input invalid');
      } else {
        console.error(err.toString());
        res.status(500).send('Server error');
      }
    });
    
    0 讨论(0)
  • 2020-12-02 12:21

    try-catch-finally.js

    Using try-catch-finally.js, you can call the _try function with an anonymous callback, which it will call, and you can chain .catch calls to catch specific errors, and a .finally call to execute either way.

    Example

    _try(function () {
        throw 'My error';
    })
    .catch(Error, function (e) {
        console.log('Caught Error: ' + e);
    })
    .catch(String, function (e) {
        console.log('Caught String: ' + e);
    })
    .catch(function (e) {
        console.log('Caught other: ' + e);
    })
    .finally(function () {
        console.log('Error was caught explicitly');
    });
    

    Example with modern arrow functions and template literals

    _try(() => {
      throw 'My error';
    }).catch(Error, e => {
      console.log(`Caught Error: ${e}`);
    }).catch(String, e => {
      console.log(`Caught String: ${e}`);
    }).catch(e => {
      console.log(`Caught other: ${e}`);
    }).finally(() => {
      console.log('Error was caught explicitly');
    });
    
    0 讨论(0)
  • 2020-12-02 12:28
        <li>
          <span>onWarning:</span>
          <span id="msg_warning"></span>
        </li>
    
      try {
      // load face detection model
      await changeFaceDetector(MTCNN)
      changeInputSize(128)
    
      // try to access users webcam and stream the images
      // to the video element
    
        const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
        const videoEl = $('#inputVideo').get(0)
        videoEl.srcObject = stream
      }
      catch(err) {
        //$("#msg_error").html(`Requested device not found`);
        $("#msg_error").html(err.message);
        console.log(err.message);
      }
    
    0 讨论(0)
  • 2020-12-02 12:29

    To create custom exceptions, you can inherit from the Error object:

    function SpecificError () {
    
    }
    
    SpecificError.prototype = new Error();
    
    // ...
    try {
      throw new SpecificError;
    } catch (e) {
      if (e instanceof SpecificError) {
       // specific error
      } else {
        throw e; // let others bubble up
      }
    }
    

    A minimalistic approach, without inheriting from Error, could be throwing a simple object having a name and a message properties:

    function throwSpecificError() {
      throw {
        name: 'SpecificError',
        message: 'SpecificError occurred!'
      };
    }
    
    
    // ...
    try {
      throwSpecificError();
    } catch (e) {
      if (e.name == 'SpecificError') {
       // specific error
      } else {
        throw e; // let others bubble up
      }
    }
    
    0 讨论(0)
  • 2020-12-02 12:32

    I didn't love any of these solutions so I made my own. The try-catch-finally.js is pretty cool except that if you forget one little underscore (_) before the try then the code will still run just fine, but nothing will get caught ever! Yuck.

    CatchFilter

    I added a CatchFilter in my code:

    "use strict";
    
    /**
     * This catches a specific error. If the error doesn't match the errorType class passed in, it is rethrown for a
     * different catch handler to handle.
     * @param errorType The class that should be caught
     * @param funcToCall The function to call if an error is thrown of this type
     * @return {Function} A function that can be given directly to the `.catch()` part of a promise.
     */
    module.exports.catchOnly = function(errorType, funcToCall) {
      return (error) => {
        if(error instanceof errorType) {
          return funcToCall(error);
        } else {
          // Oops, it's not for us.
          throw error;
        }
      };
    };
    

    Now I can filter

    Now I can filter like in C# or Java:

    new Promise((resolve, reject => {
       <snip><snip>
    }).catch(CatchFilter.catchOnly(MyError, err =>
       console.log("This is for my error");
    }).catch(err => {
       console.log("This is for all of the other errors.");
    });
    
    0 讨论(0)
提交回复
热议问题