目次
相对友好但糟糕的处理方式
unhandledrejection 事件获取 Promise 错误
ホームページ ウェブフロントエンド jsチュートリアル JavaScript のエラー例外の分析 (例付き)

JavaScript のエラー例外の分析 (例付き)

Apr 04, 2019 am 11:22 AM
error javascript 例外処理 間違い

この記事の内容は JavaScript のエラーと例外の分析に関するものです (例付き)。一定の参考価値があります。困っている友人が参考になれば幸いです。手伝う。

私のアドバイスは、エラーを隠すのではなく、勇気を持ってエラーを破棄することです。コードのバグによってプログラムがクラッシュしても、誰も恥じることはありません。プログラムを中断して、ユーザーが最初からやり直せるようにすることができます。間違いは避けられず、それにどう対処するかが重要です。

JavaScript は、一連のエラー処理メカニズムを提供します。エラーとは、プログラムの通常のフローを妨げる異常な事故です。では、オンラインにした後に特別なバグに遭遇した場合、どうすれば問題をより早く特定できるでしょうか?これが私たちのトピックで議論する必要があることです。

以下では、JavaScript Error の基本的な知識、例外をインターセプトしてキャプチャする方法、オンラインでエラーを簡単に報告する方法について説明します。また、インターネット上の知識ポイントに基づいていくつかの要約と分析を作成しました (私は単なるインターネットのポーターです)(作成者ではなく作業者です))、間違いや脱落がある場合は、その問題に関して私を厳しく批判してください。

このトピックは現在ブラウザーを対象としており、node.js は考慮されていませんが、これらはすべて JavaScript Es6 構文であり、類似しています。

JavaScript がエラーをスローするのはどのような場合ですか?

一般に 2 つの状況に分けられます。

JavaScript にエラーが発生する

開発者によって積極的にスローされるエラー

JavaScript エンジンが自動的にスローするエラー

ほとんどのシナリオで発生するエラーは、このタイプのエラーです。 Javascript の構文エラー、コード参照エラー、型エラーなどが発生した場合、JavaScript エンジンは自動的にそのようなエラーをトリガーします。いくつかのシナリオは次のとおりです。

シナリオ 1

console.log(a.notExited)
// 浏览器会抛出 Uncaught ReferenceError: a is not defined
ログイン後にコピー

シナリオ 2

const a;
// 浏览器抛出 Uncaught SyntaxError: Missing initializer in const declaration
ログイン後にコピー

構文エラー。ブラウザは通常、できるだけ早くエラーをスローし、実行まで待機しません。エラー。

シナリオ 3

let data;
data.forEach(v=>{})
// Uncaught TypeError: Cannot read property 'forEach' of undefined
ログイン後にコピー

手動でスローされたエラー

は、通常、クラス ライブラリによって開発されたカスタム エラー例外です (パラメーターがスローされるなどの不正なエラー例外など)。または、理解を容易にするためにエラー メッセージを再修正して報告してください。

シーン 1

function sum(a,b){
  if(typeof a !== 'number') {
    throw TypeError('Expected a to be a number.');
  }
  if(typeof b !== 'number') {
    throw TypeError('Expected b to be a number.');
  }
  return a + b;
}
sum(3,'d');
// 浏览器抛出 uncaught TypeError: Expected b to be a number.
ログイン後にコピー

シナリオ 2

もちろん、必ずしもこれを行う必要はありません。

let data;

try {
  data.forEach(v => {});
} catch (error) {
  error.message = 'data 没有定义,data 必须是数组。';
  error.name = 'DataTypeError';
  throw error;
}
ログイン後にコピー

Error オブジェクトを作成するにはどうすればよいですか?

作成構文は次のとおりです。

new Error([message[,fileName,lineNumber]])
ログイン後にコピー

新しい構文を省略した場合も同様です。

fileName と lineNumber はすべてのブラウザと互換性があるわけではなく、Google もサポートしていないため、無視してかまいません。

Error コンストラクターは一般的なエラー型であり、Error 型の他に、TypeError、RangeError などの型もあります。

エラー例

ここにリストされているのは、エラー層のプロトタイプ チェーンのプロパティとメソッドです。より深いプロトタイプ チェーンの継承プロパティと利便性については説明しません。一部の互換性のある、一般的ではないプロパティおよびメソッドについては説明されていません。

console.log(Error.prototype)
// 浏览器输出 {constructor: ƒ, name: "Error", message: "", toString: ƒ}
ログイン後にコピー

他のエラー型コンストラクターは Error を継承し、インスタンスは一貫しています。

プロパティ

Error.prototype.message

エラー メッセージ、Error("msg").message === "msg"。

Error.prototype.name

エラー タイプ (名前)、Error("msg").name === "エラー"。 TypeError の場合、名前は TypeError です。

Error.prototype.stack

Error オブジェクトは、非標準のスタック属性として関数トレース メソッドを提供します。関数がどのモードから、どの行またはファイルから、どのようなパラメータで呼び出されるかは関係ありません。このスタックは最も古い最近の呼び出しから生成され、元のグローバル スコープ呼び出しを返します。

これは仕様ではなく、互換性があります。テストの結果、Google、Firefox、Edge、Safari はすべてこの機能をサポートしています (すべて最新バージョン 2019-04-02 でテスト済み) が、IE はこの機能をサポートしていません。

Method

Error.prototype.constructor

Error.prototype.toString

戻り値の形式は ${name} です: ${メッセージ}。

一般的に使用されるエラー タイプ

一般的なエラー コンストラクターに加えて、JavaScript には他の 5 つの一般的なエラー コンストラクターもあります。

TypeError

エラー インスタンスを作成して、エラーの原因を示します: 変数またはパラメーターが有効な型に属していません。

throw TypeError("类型错误");
// Uncaught TypeError: 类型错误
ログイン後にコピー

RangeError

エラー インスタンスを作成して、エラーの原因を示します。数値変数またはパラメータが有効範囲を超えています。

throw RangeError("数值超出有效范围");
// Uncaught RangeError: 数值超出有效范围
ログイン後にコピー

ReferenceError

エラーの原因を示すエラー インスタンスを作成します: 無効な参照。

throw ReferenceError("无效引用");
// Uncaught ReferenceError: 无效引用
ログイン後にコピー

SyntaxError

エラーの原因: 構文エラーを示す Error インスタンスを作成します。クラス ライブラリが新しい構文 (テンプレート構文など) を定義しない限り、このシナリオはほとんど使用されません。

throw SyntaxError("语法错误");
// Uncaught SyntaxError: 语法错误
ログイン後にコピー

URIError

エラーの原因を示す Error インスタンスを作成します: URI 関連のエラー。

throw URIError("url 不合法");
// Uncaught RangeError: url 不合法
ログイン後にコピー

自定义 Error 类型

自定义新的 Error 类型需要继承 Error ,如下自定义 CustomError:

function CustomError(...args){
  class InnerCustomError extends Error {
    name = "CustomError";
  }
  return new InnerCustomError(...args);
}
ログイン後にコピー

继承 Error 后,我们只需要对 name 做重写,然后封装成可直接调用的函数即可。

如何拦截 JavaScript 错误?

既然没人能保证 web 应用不会出现 bug,那么出现异常报错时,如何拦截并进行一些操作呢?

try…catch… 拦截

这是拦截 JavaScript 错误,拦截后,如果不手动抛出错误,这个错误将静默处理。平常写代码如果我们知道某段代码可能会出现报错问题,就可以使用这种方式。如下:

const { data } = this.props;
try {
  data.forEach(d=>{});
  // 如果 data 不是数组就会报错
} catch(err){
  console.error(err);
  // 这里可以做上报处理等操作
}
ログイン後にコピー

一些使用方式

十分不友好的处理方式

try...catch... 使用需要注意,try…catch… 后,错误会被拦截,如果不主动抛出错误,那么无法知道报错位置。如下面的处理方式就是不好的。

function badHandler(fn) {
  try {
    return fn();
  } catch (err) { /**noop,不做任何处理**/ }
  return null;
}
badHandler();
ログイン後にコピー

这样 fn 回调发送错误后,我们无法知道错误是在哪里发生的,因为已经被 try…catch 了,那么如何解决这个问题呢?

相对友好但糟糕的处理方式
function CustomError(...args){
  class InnerCustomError extends Error {
    name = "CustomError";
  }
  return new InnerCustomError(...args);
}
function uglyHandlerImproved(fn) {
  try {
    return fn();
  } catch (err) { 
    throw new CustomError(err.message);
  }
  return null;
}
badHandler();
ログイン後にコピー

现在,这个自定义的错误对象包含了原本错误的信息,因此变得更加有用。但是因为再度抛出来,依然是未处理的错误。

try…catch… 可以拦截异步错误吗?

这个也要分场景,也看个人的理解方向,首先理解下面这句话:

try…catch 只会拦截当前执行环境的错误,try 块中的异步已经脱离了当前的执行环境,所以 try…catch… 无效。

setTimeout 和 Promise 都无法通过 try…catch 捕获到错误,指的是 try 包含异步(非当前执行环境),不是异步包含 try(当前执行环境)。异步无效和有效 try…catch 如下:

setTimeout

这个无效:

try {
  setTimeout(() => {
    data.forEach(d => {});
  });
} catch (err) {
  console.log('这里不会运行');
}
ログイン後にコピー
ログイン後にコピー

下面的 try…catch 才会有效:

setTimeout(() => {
  try {
    data.forEach(d => {});
  } catch (err) {
    console.log('这里会运行');
  }
});
ログイン後にコピー
ログイン後にコピー

Promise

这个无效:

try {
  new Promise(resolve => {
    data.forEach(d => {});
    resolve();
  });
} catch (err) {
  console.log('这里不会运行');
}
ログイン後にコピー

下面的 try…catch 才会有效:

new Promise(resolve => {
  try {
    data.forEach(d => {});
  } catch (err) {
    console.log('这里会运行');
  }
});
ログイン後にコピー

小结

不是所有场景都需要 try…catch… 的,如果所有需要的地方都 try…catch,那么代码将变得臃肿,可读性变差,开发效率变低。那么我需要统一获取错误信息呢?有没有更好的处理方式?当然有,后续会提到。

Promise 错误拦截

Promise.prototype.catch 可以达到 try…catch 一样的效果,只要是在 Promise 相关的处理中报错,都会被 catch 到。当然如果你在相关回调函数中 try…catch,然后做了静默提示,那么也是 catch  不到的。

如下会被 catch 到:

new Promise(resolve => {
  data.forEach(v => {});
}).catch(err=>{/*这里会运行*/})
ログイン後にコピー

下面的不会被 catch 到:

new Promise(resolve => {
  try {
      data.forEach(v => {});
  }catch(err){}
}).catch(err=>{/*这里不会运行*/})
ログイン後にコピー

Promise 错误拦截,这里就不详细说了,如果你看懂了 try…catch,这个也很好理解。

setTimeout 等其他异步错误拦截呢?

目前没有相关的方式直接拦截 setTimeout 等其他异步操作。

如果要拦截 setTimeout 等异步错误,我们需要在异步回调代码中处理,如:

setTimeout(() => {
  try {
    data.forEach(d => {});
  } catch (err) {
    console.log('这里会运行');
  }
});
ログイン後にコピー
ログイン後にコピー

这样可以拦截到 setTimeout 回调发生的错误,但是如果是下面这样 try…catch 是无效的:

try {
  setTimeout(() => {
    data.forEach(d => {});
  });
} catch (err) {
  console.log('这里不会运行');
}
ログイン後にコピー
ログイン後にコピー

如何获取 JavaScript 错误信息?

你可以使用上面拦截错误信息的方式获取到错误信息。但是呢,你要每个场景都要去拦截一遍吗?首先我们不确定什么地方会发生错误,然后我们也不可能每个地方都去拦截错误。

不用担心,JavaScript 也考虑到了这一点,提供了一些便捷的获取方式(不是拦截,错误还是会终止程序的运行,除非主动拦截了)。

window.onerror 事件获取错误信息

onerror 事件无论是异步还是非异步错误(除了 Promise 错误),onerror 都能捕获到运行时错误。

需要注意一下几点:

window.onerror 函数只有在返回 true 的时候,异常才不会向上抛出,否则即使是知道异常的发生控制台还是会显示 Uncaught Error: xxxxx。如果使用 addEventListener,event.preventDefault() 可以达到同样的效果。

window.onerror 是无法捕获到网络异常的错误、

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Windows Update プロンプト エラー 0x8024401c エラーの解決策 Windows Update プロンプト エラー 0x8024401c エラーの解決策 Jun 08, 2024 pm 12:18 PM

目次 解決策 1 解決策 21. Windows Update の一時ファイルを削除します。 2. 破損したシステム ファイルを修復します。 3. レジストリ エントリを表示および変更します。 4. ネットワーク カード IPv6 をオフにします。 5. WindowsUpdateTroubleshooter ツールを実行して修復します。 6. ファイアウォールをオフにします。およびその他の関連するウイルス対策ソフトウェア。 7. WidowsUpdate サービスを閉じます。解決策 3 解決策 4 Huawei コンピュータの Windows アップデート中に「0x8024401c」エラーが発生する 症状 問題 原因 解決策 まだ解決されませんか?最近、システムの脆弱性のため、Web サーバーを更新する必要があります。サーバーにログインすると、エラー コード 0x8024401c が表示されます。

C++ 関数の例外とマルチスレッド: 同時環境でのエラー処理 C++ 関数の例外とマルチスレッド: 同時環境でのエラー処理 May 04, 2024 pm 04:42 PM

C++ での関数例外処理は、マルチスレッド環境でスレッドの安全性とデータの整合性を確保するために特に重要です。 try-catch ステートメントを使用すると、特定の種類の例外が発生したときにそれをキャッチして処理し、プログラムのクラッシュやデータの破損を防ぐことができます。

Java 関数の再帰呼び出しと例外処理の間にはどのような関係がありますか? Java 関数の再帰呼び出しと例外処理の間にはどのような関係がありますか? May 03, 2024 pm 06:12 PM

再帰呼び出しでの例外処理: 再帰の深さの制限: スタック オーバーフローの防止。例外処理を使用する: try-catch ステートメントを使用して例外を処理します。末尾再帰の最適化: スタックのオーバーフローを回避します。

C++ 例外処理はカスタム エラー処理ルーチンをどのようにサポートしますか? C++ 例外処理はカスタム エラー処理ルーチンをどのようにサポートしますか? Jun 05, 2024 pm 12:13 PM

C++ 例外処理を使用すると、例外をスローし、try-catch ブロックを使用して例外をキャッチすることで実行時エラーを処理するカスタム エラー処理ルーチンを作成できます。 1. 例外クラスから派生したカスタム例外クラスを作成し、what() メソッドをオーバーライドします。 2. throw キーワードを使用して例外をスローし、例外のタイプを指定します。扱った。

C++ ラムダ式で例外を処理するにはどうすればよいですか? C++ ラムダ式で例外を処理するにはどうすればよいですか? Jun 03, 2024 pm 03:01 PM

C++ ラムダ式の例外処理には独自のスコープがなく、デフォルトでは例外はキャッチされません。例外をキャッチするには、ラムダ式キャッチ構文を使用できます。これにより、ラムダ式がその定義スコープ内の変数をキャプチャできるようになり、try-catch ブロックで例外処理が可能になります。

C++ テクノロジにおける例外処理: マルチスレッド環境で例外を正しく処理するにはどうすればよいですか? C++ テクノロジにおける例外処理: マルチスレッド環境で例外を正しく処理するにはどうすればよいですか? May 09, 2024 pm 12:36 PM

マルチスレッド C++ では、例外処理は適時性、スレッドの安全性、明確性という原則に従います。実際には、ミューテックスまたはアトミック変数を使用することで、例外処理コードのスレッド セーフを確保できます。さらに、例外処理コードの再入性、パフォーマンス、テストを考慮して、コードがマルチスレッド環境で安全かつ効率的に実行されることを確認してください。

PHP 例外処理: 例外追跡を通じてシステムの動作を理解する PHP 例外処理: 例外追跡を通じてシステムの動作を理解する Jun 05, 2024 pm 07:57 PM

PHP 例外処理: 例外追跡を通じてシステムの動作を理解する 例外は、PHP がエラーを処理するために使用するメカニズムであり、例外は例外ハンドラーによって処理されます。例外クラス Exception は一般的な例外を表し、Throwable クラスはすべての例外を表します。 throw キーワードを使用して例外をスローし、try...catch ステートメントを使用して例外ハンドラーを定義します。実際のケースでは、例外処理を使用して、calculate() 関数によってスローされる DivisionByZeroError をキャプチャして処理し、エラー発生時にアプリケーションが適切に失敗できるようにします。

PHPで例外を効果的に処理する方法(試して、キャッチ、最後に、スロー)? PHPで例外を効果的に処理する方法(試して、キャッチ、最後に、スロー)? Apr 05, 2025 am 12:03 AM

PHPでは、Try、Catch、最後にキーワードをスローすることにより、例外処理が達成されます。 1)TRYブロックは、例外をスローする可能性のあるコードを囲みます。 2)キャッチブロックは例外を処理します。 3)最後にブロックは、コードが常に実行されることを保証します。 4)スローは、例外を手動でスローするために使用されます。これらのメカニズムは、コードの堅牢性と保守性を向上させるのに役立ちます。

See all articles