1# 错误管理开发指导
2
3## 场景介绍
4
5当应用的代码存在规范问题或错误时,会在运行中产生异常和错误,如应用未捕获异常、应用生命周期超时等。在错误产生后,应用会异常退出。错误日志通常会保存在用户本地存储上,不方便开发者定位问题。所以,应用开发者可以使用错误管理的接口,在应用退出前,及时将相关错误及日志上报到开发者的服务平台来定位问题。
6
7使用errormanager接口监听异常和错误后,应用不会退出,建议在回调函数执行完后,增加同步退出操作,如果只是为了获取错误日志,建议使用[hiappevent](hiappevent-watcher-crash-events-arkts.md)。
8
9## 接口说明
10
11应用错误管理接口由[errorManager](../reference/apis-ability-kit/js-apis-app-ability-errorManager.md)模块提供,开发者可以通过import引入,详见[开发示例](#开发示例)。
12
13**错误管理接口功能介绍:**
14
15| 接口名称                                                       | 说明                                                 |
16| ------------------------------------------------------------ | ---------------------------------------------------- |
17| on(type: "error", observer: ErrorObserver): number       | 注册错误监听接口,当系统监测到应用异常时会回调该监听。该接口为同步接口,返回值为注册的监听对象对应的序号。 |
18| off(type: "error", observerId: number,  callback: AsyncCallback\<void\>): void | 以callback的形式解除注册监听,传入的number为之前注册监听时返回的序号。  |
19| off(type: "error", observerId: number): Promise\<void\> | 以Promise的形式解除注册监听,传入的number为之前注册监听时返回的序号。  |
20| on(type: 'loopObserver', timeout: number, observer: LoopObserver): void<sup>12+</sup> | 注册主线程消息处理耗时监听器,当系统监测到应用主线程事件处理超时时会回调该监听。只能在主线程调用,多次注册后,后一次的注册会覆盖前一次的。  |
21| off(type: 'loopObserver', observer?: LoopObserver): void<sup>12+</sup> | 解除应用主线程消息处理耗时监听。  |
22
23当采用callback作为异步回调时,可以在callback中进行下一步处理。当采用Promise对象返回时,可以在Promise对象中类似地处理接口返回值。具体结果码说明见[解除注册结果码](#解除注册结果码)。
24
25
26**错误监听(ErrorObserver)接口功能介绍:**
27
28| 接口名称                         | 说明                                                         |
29| ------------------------------ | ------------------------------------------------------------ |
30| onUnhandledException(errMsg: string): void | 系统回调接口,应用注册后,当应用产生未捕获的异常时的回调。 |
31| onException?(errObject: Error): void | 系统回调接口,应用注册后,当应用产生异常上报js层时的回调。 |
32
33
34**应用主线程监听(LoopObserver)接口功能介绍:**
35
36| 接口名称                         | 说明                                                         |
37| ------------------------------ | ------------------------------------------------------------ |
38| onLoopTimeOut?(timeout: number): void<sup>12+</sup> | 系统回调接口,应用注册后,当应用主线程处理事件超时的回调。 |
39
40
41### 解除注册结果码
42
43| 结果码 | 原因                        |
44| ------ | ---------------------------  |
45| 0      |  正常返回                          |
46| -1     | 传入的number不存在              |
47| -2     | 参数错误       |
48
49## 开发示例
50
51> **注意:**
52> 建议在异常回调函数处理的最后,增加同步退出操作,否则可能出现多次异常回调的现象。
53
54```ts
55import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
56import { window } from '@kit.ArkUI';
57import process from '@ohos.process';
58
59let registerId = -1;
60let callback: errorManager.ErrorObserver = {
61    onUnhandledException: (errMsg) => {
62        console.log(errMsg);
63    },
64    onException: (errorObj) => {
65        console.log('onException, name: ', errorObj.name);
66        console.log('onException, message: ', errorObj.message);
67        if (typeof(errorObj.stack) === 'string') {
68            console.log('onException, stack: ', errorObj.stack);
69        }
70        //回调函数执行完,采用同步退出方式,避免多次触发异常
71        let pro = new process.ProcessManager();
72        pro.exit(0);
73    }
74}
75
76let abilityWant: Want;
77
78export default class EntryAbility extends UIAbility {
79    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
80        console.log("[Demo] EntryAbility onCreate");
81        registerId = errorManager.on("error", callback);
82        abilityWant = want;
83    }
84
85    onDestroy() {
86        console.log("[Demo] EntryAbility onDestroy");
87        errorManager.off("error", registerId, (result) => {
88            console.log("[Demo] result " + result.code + ";" + result.message);
89        });
90    }
91
92    onWindowStageCreate(windowStage: window.WindowStage) {
93        // Main window is created, set main page for this ability
94        console.log("[Demo] EntryAbility onWindowStageCreate");
95
96        windowStage.loadContent("pages/index", (err, data) => {
97            if (err.code) {
98                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
99                return;
100            }
101            console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
102        });
103    }
104
105    onWindowStageDestroy() {
106        // Main window is destroyed, release UI related resources
107        console.log("[Demo] EntryAbility onWindowStageDestroy");
108    }
109
110    onForeground() {
111        // Ability has brought to foreground
112        console.log("[Demo] EntryAbility onForeground");
113    }
114
115    onBackground() {
116        // Ability has back to background
117        console.log("[Demo] EntryAbility onBackground");
118    }
119};
120```
121