Heim  >  Artikel  >  Web-Frontend  >  Erläuterung der JavaScript-Ausnahmebehandlung

Erläuterung der JavaScript-Ausnahmebehandlung

一个新手
一个新手Original
2017-10-25 14:49:331490Durchsuche

Wenn die JavaScript-Engine den JavaScript-Code ausführt, können verschiedene Ausnahmen auftreten, z. B. Syntaxausnahmen, fehlende Funktionen in der Sprache und eine abnormale Ausgabe vom Server oder Benutzer, die dazu führt Anomalien.

Die Javascript-Engine ist Single-Threaded. Sobald also eine Ausnahme auftritt, stoppt die Javascript-Engine normalerweise die Ausführung, blockiert nachfolgenden Code und löst eine Ausnahmemeldung aus Bei vorhersehbaren Ausnahmen sollten wir sie abfangen und Benutzern oder Entwicklern korrekt anzeigen.

Fehlerobjekt

throw und Promise.reject() können Ausnahmen vom Typ Zeichenfolge auslösen und einen Fehler auslösen Ausnahme des Objekttyps.

Eine Ausnahme des Objekttyps Error enthält nicht nur Ausnahmeinformationen, sondern auch einen Traceback-Stack, sodass Sie die Anzahl der Codezeilen, in denen der Fehler auftritt, leicht ermitteln können Traceback-Stack.

Es wird daher empfohlen, eine Fehler-Objekttypausnahme anstelle einer Zeichenfolgentypausnahme auszulösen.

Erstellen Sie Ihren eigenen Ausnahmekonstruktor

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;

Werfen Sie benutzerdefinierte Ausnahmetypen in den Code und fangen Sie sie ab

try {
    throw new MyError("some message");
} catch(e){
    console.log(e.name + ":" + e.message);
}

Auslösen

throw expression;
throw

-Anweisung wird verwendet, um eine benutzerdefinierte Ausnahme auszulösen. Die Ausführung der aktuellen Funktion wird gestoppt (Anweisungen nach throw werden nicht ausgeführt) und die Steuerung wird an den ersten catch-Block im Aufrufstapel übergeben. Wenn in der Aufruffunktion kein catch-Block vorhanden ist, wird das Programm beendet.

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

// before throw error
// throw error

try {
   try_statements
}
[catch (exception) {
   catch_statements
}]
[finally {
   finally_statements
}]
Try/Catch

wird hauptsächlich zum Abfangen von Ausnahmen verwendet. Die try/catch-Anweisung enthält einen try-Block und mindestens einen catch-Block oder einen finally-Block. Es folgen drei Formen Die try-Anweisung:

    try...catch
  • try...finally
  • versuchen...fangen...endlich
versuchen

Fügen Sie Anweisungen oder Funktionen ein, die Ausnahmen erzeugen können catch

-Block enthält die auszuführende Anweisung. Wenn eine Ausnahme im

try-Block ausgelöst wird, erfasst der catch-Block die Ausnahmeinformationen und führt catch-Block: Wenn im try-Block keine Ausnahme ausgelöst wird, wird dieser catch-Block übersprungen. Der Block finally wird nach dem Block

try

und dem Block catch ausgeführt. Es wird immer ausgeführt, unabhängig davon, ob eine Ausnahme ausgelöst oder abgefangen wird. Wenn Ausnahmeinformationen im Block finally ausgelöst werden, werden die Ausnahmeinformationen im Block try überschrieben. Wenn ein Wert vom finally

-Block zurückgegeben wird, wird dieser Wert zum Rückgabewert des gesamten
try {
    try {
        throw new Error('can not find it1');
    } finally {
        throw new Error('can not find it2');
    }
} catch (err) {
    console.log(err.message);
}

// can not find it2
try-catch-finally

, unabhängig davon ob es einen finally-Block gibt. Die 🎜>return-Anweisungen sind in try und catch. Dazu gehören Ausnahmen, die innerhalb von catch-Blöcken ausgelöst werden. Try/Catch-Leistung

function test() {
    try {
        throw new Error('can not find it1');
        return 1;
    } catch (err) {
        throw new Error('can not find it2');
        return 2;
    } finally {
        return 3;
    }
}

console.log(test()); // 3
Ein bekanntes Anti-Optimierungsmuster ist die Verwendung von

Try/Catch

.

Die in V8 verwendeten try/catch

-Anweisungen (die gleiche Situation kann in anderen JS-Engines auftreten) können vom V8-Compiler nicht optimiert werden. Weitere Informationen finden Sie unter http://www.html5rocks.com/en/tutorials/speed/v8/

window.onerror

, indem Sie einen Ereignis-Listener für

window.onerror

definieren Funktionen und nicht abgefangene Ausnahmen, die von anderen Codes im Programm generiert werden, werden häufig von der oben registrierten Überwachungsfunktion

window.onerror erfasst. Und erfassen Sie gleichzeitig einige Informationen über die Ausnahme.

window.onerror = function (message, source, lineno, colno, error) { }
    : Ausnahmeinformationen (Zeichenfolge)
  • message

  • : Skript-URL, unter der die Ausnahme aufgetreten ist (Zeichenfolge)
  • source

  • : Die Zeilennummer (Nummer), in der die Ausnahme aufgetreten ist.
  • lineno

  • : Die Spaltennummer (Nummer), in der die Ausnahme aufgetreten ist aufgetreten
  • colno

  • : Fehlerobjekt (Objekt)
  • error

    Hinweis: Safari und IE10 unterstützen
  • window.onerror Der fünfte Parameter, der in der Rückruffunktion verwendet wird, ist ein
Error

-Objekt mit einem Traceback-Stack try/catch, der keine Ausnahmen im asynchronen Code abfangen kann löst die Ausnahme global aus und

window.onerror

kann sie abfangen. In Chrome kann

window.onerror
try {
    setTimeout(() => {
        throw new Error("some message");
    }, 0);
} catch (err) {
    console.log(err);
}
// Uncaught Error: some message
Ausnahmen in Skriptdateien erkennen, auf die von anderen Domänen verwiesen wird, und diese Ausnahmen als
window.onerror = (msg, url, line, col, err) => {
    console.log(err);
}
setTimeout(() => {
    throw new Error("some message");
}, 0);
// Error: some message
markieren. Wenn Sie diese aus anderen Domänen importierten Skriptdateien nicht verarbeiten möchten, können Sie sie über das Tag

im Programm herausfiltern. In Firefox, Safari oder IE11 werden jedoch keine domänenübergreifenden JS-Ausnahmen eingeführt. Selbst in Chrome erkennt Chrome diese nicht mehr, wenn Sie try/catch verwenden domänenübergreifende Ausnahmen. Script error

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

Promise中的异常

Promise中抛出异常

new Promise((resolve,reject)=>{
    reject();
})
Promise.resolve().then((resolve,reject)=>{
    reject();
});
Promise.reject();
throw expression;

Promise中捕捉异常

promiseObj.then(undefined, (err)=>{
    catch_statements
});
promiseObj.catch((exception)=>{
    catch_statements
})

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

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

without return

Promise.resolve()
.then(() => {
    console.log('before excute reject');
    reject(new Error('throw error'));
    console.log('after excute reject');
})
.catch((err) => {
    console.log(err.message);
});

// before excute reject
// throw error
// after excute reject

use return

Promise.resolve()
.then(() => {
    console.log('before excute reject');
    return reject(new Error('throw error'));
    console.log('after excute reject');
})
.catch((err) => {
    console.log(err.message);
});

// before excute reject
// throw error

Throw or Reject

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

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

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

Promise.resolve()
.then(() => {
    setTimeout(()=>{
        throw new Error('throw error');
    },0);
})
.catch((err) => {
    console.log(err);
});

// Uncaught Error: throw error
Promise.resolve()
.then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('throw error'));
        }, 0);
    });
})
.catch((err) => {
    console.log(err);
});

// Error: throw error

window.onunhandledrejection

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

window.onunhandledrejection = event => { 
    console.log(event.reason);
}

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

let p = Promise.reject(new Error('throw error'));

setTimeout(()=>{
    p.catch(e=>{console.log(e)});
},1000);

// Uncaught (in promise) Error: throw error
// 1秒后输出
// Error: throw error
// rejection handled

统一异常处理

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

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

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

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

function EnsureError(message = 'Default Message') {
    this.name = 'EnsureError';
    this.message = message;
    this.stack = (new Error()).stack;
}
EnsureError.prototype = Object.create(Error.prototype);
EnsureError.prototype.constructor = EnsureError;

export default EnsureError;

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

function ToastError(message = 'Default Message') {
    this.name = 'ToastError';
    this.message = message;
    this.stack = (new Error()).stack;
}
ToastError.prototype = Object.create(Error.prototype);
ToastError.prototype.constructor = ToastError;

export default ToastError;

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

function DevError(message = 'Default Message') {
    this.name = 'ToastError';
    this.message = message;
    this.stack = (new Error()).stack;
}
DevError.prototype = Object.create(Error.prototype);
DevError.prototype.constructor = DevError;

export default DevError;

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

import EnsureError from './ensureError.js';
import ToastError from './toastError.js';
import DevError from './devError.js';
import EnsurePopup from './ensurePopup.js';
import ToastPopup from './toastPopup.js';

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;


Das obige ist der detaillierte Inhalt vonErläuterung der JavaScript-Ausnahmebehandlung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn