diff --git a/zh-cn/application-dev/dfx/jscrash-guidelines.md b/zh-cn/application-dev/dfx/jscrash-guidelines.md index 48da4efc99e82a9ed9e99b1722d29c46b77ef176..43c666114cc0698d0f8d8bf798c06361c6e2fd23 100644 --- a/zh-cn/application-dev/dfx/jscrash-guidelines.md +++ b/zh-cn/application-dev/dfx/jscrash-guidelines.md @@ -378,7 +378,122 @@ throw new Error("TEST JS ERROR") 遇到这类问题的解决思路,仍旧是通过故障日志定位到具体的代码行,检视上下文来分析问题即可。 -#### 案例二:因未处理三方接口抛出的JS异常导致的JS Crash问题 +#### 案例二:捕获异常后重新抛出场景下的异常调用栈 + +在某些开发场景下,代码产生JS异常后并不会被立即抛出,开发者会在其它位置捕获JS异常,并做定制化处理后抛出。 + +1. 例如,使用ErrorManager可以捕获当前线程中未被捕获到的promise rejection: + + ```typescript + import { errorManager } from '@kit.AbilityKit'; + + let observer: errorManager.UnhandledRejectionObserver = (e: Error) => { + if (e instanceof Error) { + throw e; // 捕获Error后直接抛出 + } + }; + + errorManager.on('unhandledRejection', observer); + + async function myAsyncFunction(): Promise { + const result: string = await new Promise(()=>{ + throw new Error('uncaught error'); + }); + return result; + } + + myAsyncFunction(); + ``` + + JS Crash日志核心内容如下,Stacktrace展示的异常调用栈为异常产生的位置,而不是最终在observer抛出异常导致JS Crash的位置: + + ```text + Reason:Error + Error name:Error + Error message:uncaught error + Stacktrace: + at anonymous (entry/src/main/ets/pages/Index.ets:37:11) + at myAsyncFunction (entry/src/main/ets/pages/Index.ets:36:32) + at func_main_0 (entry/src/main/ets/pages/Index.ets:42:1) + ``` + +2. 如果开发者期望在JS Crash的Stacktrace中,展示最终抛出异常导致JS Crash的调用栈,可在捕获到异常后new一个新的异常并抛出: + + ```typescript + import { errorManager } from '@kit.AbilityKit'; + + let observer: errorManager.UnhandledRejectionObserver = (e: Error) => { + if (e instanceof Error) { + throw new Error('re-throw error'); // new一个新的Error并抛出 + } + }; + + errorManager.on('unhandledRejection', observer); + + async function myAsyncFunction(): Promise { + const result: string = await new Promise(()=>{ + throw new Error('uncaught error'); + }); + return result; + } + + myAsyncFunction(); + ``` + + 此时,JS Crash日志的Stacktrace展示的异常调用栈指向observer: + + ``` + Reason:Error + Error name:Error + Error message:re-throw error + Stacktrace: + at observer (entry/src/main/ets/pages/Index.ets:29:11) + ``` + +3. 如果开发者期望在JS Crash日志中既展示异常产生的调用栈,又展示最终抛出异常导致JS Crash的调用栈,可采用如下实现方式: + + ```typescript + import { errorManager } from '@kit.AbilityKit'; + + let observer: errorManager.UnhandledRejectionObserver = (e: Error) => { + if (e instanceof Error) { + // new一个新的Error,并将原Error的stack拼接到新的Error上 + let error = new Error('re-throw error'); + error.name = e.name; + if (typeof error.stack == 'string') { + error.stack += 'Caused By:\n' + e.stack; + } + throw error; + } + }; + + errorManager.on('unhandledRejection', observer); + + async function myAsyncFunction(): Promise { + const result: string = await new Promise(()=>{ + throw new Error('uncaught error'); + }); + return result; + } + + myAsyncFunction(); + ``` + + 此时,JS Crash日志的Stacktrace展示异常产生时的调用栈,而开发者自定义的Caused By展示的是最终抛出异常导致JS Crash的调用栈: + + ```text + Reason:Error + Error name:Error + Error message:re-throw error + Stacktrace: + at observer (entry/src/main/ets/pages/Index.ets:30:18) + Caused By: + at anonymous (entry/src/main/ets/pages/Index.ets:43:11) + at myAsyncFunction (entry/src/main/ets/pages/Index.ets:42:32) + at func_main_0 (entry/src/main/ets/pages/Index.ets:48:1) + ``` + +#### 案例三:因未处理三方接口抛出的JS异常导致的JS Crash问题 1. 获取JS Crash 日志核心内容如下