Maison > interface Web > js tutoriel > le corps du texte

Explication de la gestion des exceptions JavaScript

一个新手
Libérer: 2017-10-25 14:49:33
original
1482 Les gens l'ont consulté

Lorsque le moteur JavaScript exécute le code JavaScript, diverses exceptions peuvent se produire, telles que des exceptions de syntaxe, des fonctionnalités manquantes dans le langage et une sortie anormale du serveur ou de l'utilisateur entraînant anomalies.

Le moteur Javascript est monothread, donc une fois qu'une exception est rencontrée, le moteur Javascript arrête généralement l'exécution, bloque le code suivant et renvoie un message d'exception, donc Pour les exceptions prévisibles, nous devons les détecter et les afficher correctement aux utilisateurs ou aux développeurs.

Objet d'erreur

throw et Promise.reject() peuvent lancer des exceptions de type chaîne et peuvent lancer une Erreur Exception de type d'objet.

Une exception du type d'objet Erreur contient non seulement des informations d'exception, mais contient également une pile de traçage afin que vous puissiez facilement trouver le nombre de lignes de code où l'erreur se produit via le pile de traçage.

Il est donc recommandé de lancer une exception de type d'objet Erreur au lieu d'une exception de type chaîne.

Créez votre propre constructeur d'exceptions

function MyError(message) {
    var instance = new Error(message);
    instance.name = 'MyError';
    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    return instance;
}

MyError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: MyError,
        enumerable: false,
        writable: true,
        configurable: true
    }
});

if (Object.setPrototypeOf) {
    Object.setPrototypeOf(MyError, Error);
} else {
    MyError.__proto__ = Error;
}

export default MyError;
Copier après la connexion

Lancez des types d'exceptions personnalisés dans le code et interceptez-les

try {
    throw new MyError("some message");
} catch(e){
    console.log(e.name + ":" + e.message);
}
Copier après la connexion

Lancez

throw expression;
Copier après la connexion
Copier après la connexion
< Le 🎜>< L'instruction 🎜>throw

est utilisée pour lever une exception définie par l'utilisateur. L'exécution de la fonction actuelle sera arrêtée (les instructions après throw ne seront pas exécutées) et le contrôle sera passé au premier bloc catch de la pile d'appels. S'il n'y a pas de bloc catch dans la fonction appelante, le programme se terminera.

Try/Catch
try {
    console.log(&#39;before throw error&#39;);
    throw new Error(&#39;throw error&#39;);
    console.log(&#39;after throw error&#39;);
} catch (err) {
    console.log(err.message);
}

// before throw error
// throw error
Copier après la connexion

try {
   try_statements
}
[catch (exception) {
   catch_statements
}]
[finally {
   finally_statements
}]
Copier après la connexion
try/catch

est principalement utilisé pour intercepter les exceptions. L'instruction try/catch contient un bloc try et au moins un bloc catch ou un bloc finally. Voici trois formes. La déclaration essayer :

    essayer...attraper
  • essayer...enfin
  • essayez...catch...enfin
essayez

Mettez des instructions ou des fonctions pouvant générer des exceptions < Le 🎜>< Le bloc 🎜>catch contient l'instruction à exécuter. Lorsqu'une exception est levée dans le bloc

try

, le bloc catch capturera les informations d'exception et exécutera le catch</strong>. 🎜>catch<strong> bloc, si aucune exception n'est levée dans le bloc </strong>try<strong>, ce bloc </strong>catch<strong> sera ignoré. Le bloc </strong><strong></strong>finally</p> est exécuté après le bloc <p>try<strong> et le bloc </strong>catch<strong>. Il est toujours exécuté, qu'une exception soit levée ou interceptée. Lorsque des informations d'exception sont générées dans le bloc </strong>finally<strong>, les informations d'exception dans le bloc </strong>try<strong> seront écrasées. </strong><strong></strong>Si une valeur est renvoyée par le bloc </p>finally<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">try { try { throw new Error(&amp;#39;can not find it1&amp;#39;); } finally { throw new Error(&amp;#39;can not find it2&amp;#39;); } } catch (err) { console.log(err.message); } // can not find it2</pre><div class="contentsignin">Copier après la connexion</div></div>, alors cette valeur deviendra la valeur de retour de l'ensemble du <p>try-catch-finally<strong>, quel que soit s'il y a un bloc </strong>finally<strong> Les instructions 🎜>return</strong> sont dans <strong>try</strong> et <strong>catch</strong>. Cela inclut les exceptions levées à l’intérieur des blocs <strong>catch</strong>. <strong></strong></p>Performances Try/Catch<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">function test() { try { throw new Error(&amp;#39;can not find it1&amp;#39;); return 1; } catch (err) { throw new Error(&amp;#39;can not find it2&amp;#39;); return 2; } finally { return 3; } } console.log(test()); // 3</pre><div class="contentsignin">Copier après la connexion</div></div><h3>Un modèle d'anti-optimisation bien connu consiste à utiliser </h3>try/catch<p>. <strong></strong>Les fonctions de l'instruction </p>try/catch<p> utilisée dans la V8 (la même situation peut se produire dans d'autres moteurs JS) ne peuvent pas être optimisées par le compilateur V8. Reportez-vous à http://www.html5rocks.com/en/tutorials/speed/v8/<strong></strong>window.onerror</p><h2> en définissant un écouteur d'événement sur </h2>window.onerror<p> Les fonctions, exceptions non interceptées générées par d'autres codes du programme sont souvent interceptées par la fonction d'écoute enregistrée ci-dessus <strong>window.onerror</strong>. Et en même temps, capturez des informations sur l'exception. <strong></strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">window.onerror = function (message, source, lineno, colno, error) { }</pre><div class="contentsignin">Copier après la connexion</div></div><ul class=" list-paddingleft-2"><li> : informations sur l'exception (chaîne) <p><code>message

  •  : URL du script où l'exception s'est produite (chaîne)

    source

  •  : Le numéro de ligne (numéro) où l'exception s'est produite

    lineno

  •  : Le numéro de colonne (numéro) où l'exception s'est produit

    colno

  •  : Objet d'erreur (objet)

    error

  • Remarque : Safari et IE10 ne prennent pas encore en charge window.onerror

    Le cinquième paramètre utilisé dans la fonction de rappel, qui est un objet Error avec une pile de trace

    try/catch

    ne peut pas intercepter les exceptions dans le code asynchrone. lèvera l'exception globalement et window.onerror pourra l'attraper.

    try {
        setTimeout(() => {
            throw new Error("some message");
        }, 0);
    } catch (err) {
        console.log(err);
    }
    // Uncaught Error: some message
    Copier après la connexion
    Dans Chrome,
    window.onerror = (msg, url, line, col, err) => {
        console.log(err);
    }
    setTimeout(() => {
        throw new Error("some message");
    }, 0);
    // Error: some message
    Copier après la connexion
    window.onerror

    peut détecter des exceptions dans des fichiers de script référencés à partir d'autres domaines et marquer ces exceptions comme . Si vous ne souhaitez pas traiter ces fichiers de script importés d'autres domaines, vous pouvez les filtrer via la balise du programme. Cependant, dans Firefox, Safari ou IE11, les exceptions JS inter-domaines ne seront pas introduites. Même dans Chrome, si vous utilisez Script errortry/catchScript error pour entourer ces codes malveillants, Chrome ne les détectera plus. exceptions inter-domaines.

    在Chrome中,如果你想通过 window.onerror 来获取到完整的跨域异常信息,那么这些跨域资源必须提供合适的跨域头信息。

    Promise中的异常

    Promise中抛出异常

    new Promise((resolve,reject)=>{
        reject();
    })
    Copier après la connexion
    Promise.resolve().then((resolve,reject)=>{
        reject();
    });
    Copier après la connexion
    Promise.reject();
    Copier après la connexion
    throw expression;
    Copier après la connexion
    Copier après la connexion

    Promise中捕捉异常

    promiseObj.then(undefined, (err)=>{
        catch_statements
    });
    Copier après la connexion
    promiseObj.catch((exception)=>{
        catch_statements
    })
    Copier après la connexion

    JavaScript 函数中,只有 return / yield / throw 会中断函数的执行,其他的都无法阻止其运行到结束的。

    resolve / reject 之前加上 return 能阻止往下继续运行。

    without return

    Promise.resolve()
    .then(() => {
        console.log(&#39;before excute reject&#39;);
        reject(new Error(&#39;throw error&#39;));
        console.log(&#39;after excute reject&#39;);
    })
    .catch((err) => {
        console.log(err.message);
    });
    
    // before excute reject
    // throw error
    // after excute reject
    Copier après la connexion

    use return

    Promise.resolve()
    .then(() => {
        console.log(&#39;before excute reject&#39;);
        return reject(new Error(&#39;throw error&#39;));
        console.log(&#39;after excute reject&#39;);
    })
    .catch((err) => {
        console.log(err.message);
    });
    
    // before excute reject
    // throw error
    Copier après la connexion

    Throw or Reject

    无论是 try/catch 还是 promise 都能捕获到的是“同步”异常

    reject 是回调,而 throw 只是一个同步的语句,如果在另一个异步的上下文中抛出,在当前上下文中是无法捕获到的。

    因此在 Promise 中使用 reject 抛出异常。否则 catch 有可能会捕捉不到。

    Promise.resolve()
    .then(() => {
        setTimeout(()=>{
            throw new Error(&#39;throw error&#39;);
        },0);
    })
    .catch((err) => {
        console.log(err);
    });
    
    // Uncaught Error: throw error
    Copier après la connexion
    Promise.resolve()
    .then(() => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                reject(new Error(&#39;throw error&#39;));
            }, 0);
        });
    })
    .catch((err) => {
        console.log(err);
    });
    
    // Error: throw error
    Copier après la connexion

    window.onunhandledrejection

    window.onunhandledrejectionwindow.onerror 类似,在一个JavaScript Promise 被 reject 但是没有 catch 来捕捉这个 reject时触发。并且同时捕获到一些关于异常的信息。

    window.onunhandledrejection = event => { 
        console.log(event.reason);
    }
    Copier après la connexion

    event事件是 PromiseRejectionEvent 的实例,它有两个属性:

    • event.promise:被 rejected 的 JavaScript Promise

    • event.reason:一个值或 Object 表明为什么 promise 被 rejected,是 Promise.reject() 中的内容。

    window.rejectionhandled

    因为 Promise 可以延后调用 catch 方法,若在抛出 reject 时未调用 catch 进行捕捉,但稍后再次调用 catch,此时会触发 rejectionhandled 事件。

    window.onrejectionhandled = event =>
    {
        console.log(&#39;rejection handled&#39;);
    }
    
    let p = Promise.reject(new Error(&#39;throw error&#39;));
    
    setTimeout(()=>{
        p.catch(e=>{console.log(e)});
    },1000);
    
    // Uncaught (in promise) Error: throw error
    // 1秒后输出
    // Error: throw error
    // rejection handled
    Copier après la connexion

    统一异常处理

    代码中抛出的异常,一种是要展示给用户,一种是展示给开发者。

    对于展示给用户的异常,一般使用 alerttoast 展示;对于展示给开发者的异常,一般输出到控制台。

    在一个函数或一个代码块中可以把抛出的异常统一捕捉起来,按照不同的异常类型以不同的方式展示,对于。

    需要点击确认的异常类型:
    ensureError.js

    function EnsureError(message = &#39;Default Message&#39;) {
        this.name = &#39;EnsureError&#39;;
        this.message = message;
        this.stack = (new Error()).stack;
    }
    EnsureError.prototype = Object.create(Error.prototype);
    EnsureError.prototype.constructor = EnsureError;
    
    export default EnsureError;
    Copier après la connexion

    弹窗提示的异常类型:
    toastError.js

    function ToastError(message = &#39;Default Message&#39;) {
        this.name = &#39;ToastError&#39;;
        this.message = message;
        this.stack = (new Error()).stack;
    }
    ToastError.prototype = Object.create(Error.prototype);
    ToastError.prototype.constructor = ToastError;
    
    export default ToastError;
    Copier après la connexion

    提示开发者的异常类型:
    devError.js

    function DevError(message = &#39;Default Message&#39;) {
        this.name = &#39;ToastError&#39;;
        this.message = message;
        this.stack = (new Error()).stack;
    }
    DevError.prototype = Object.create(Error.prototype);
    DevError.prototype.constructor = DevError;
    
    export default DevError;
    Copier après la connexion

    异常处理器:
    抛出普通异常时,可以带上 stackoverflow 上问题的列表,方便开发者查找原因。
    errorHandler.js

    import EnsureError from &#39;./ensureError.js&#39;;
    import ToastError from &#39;./toastError.js&#39;;
    import DevError from &#39;./devError.js&#39;;
    import EnsurePopup from &#39;./ensurePopup.js&#39;;
    import ToastPopup from &#39;./toastPopup.js&#39;;
    
    function errorHandler(err) {
        if (err instanceof EnsureError) {
            EnsurePopup(err.message);
        } else if (err instanceof ToastError) {
            ToastPopup(err.message);
        }else if( err instanceof DevError){
            DevError(err.message);
        }else{
            error.message += ` https://stackoverflow.com/questions?q=${encodeURI(error.message)}`
            console.error(err.message);    
        }
    }
    
    window.onerror = (msg, url, line, col, err) => {
        errorHandler(err);
    }
    
    window.onunhandledrejection = event =>{
        errorHandler(event.reason);
    };
    
    export default errorHandler;
    Copier après la connexion


    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Étiquettes associées:
    source:php.cn
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal