• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: 'globalErrorOccurred', observer: GlobalObserver): void       | 注册进程错误监听接口,当系统监测到应用异常时会回调该监听,该接口为同步接口,即一次注册,全局监听。(**推荐使用**)  |
21| off(type: 'globalErrorOccurred', observer?: GlobalObserver): void | 以callback的形式解除注册监听。(**推荐使用**)  |
22| on(type: 'globalUnhandledRejectionDetected', observer: GlobalObserver): void       | 注册进程错误监听接口,当系统监测到应用promise异常时会回调该监听,该接口为同步接口,即一次注册,全局监听。(**推荐使用**)  |
23| off(type: 'globalUnhandledRejectionDetected', observer?: GlobalObserver): void | 以callback的形式解除注册监听。(**推荐使用**)  |
24| on(type: 'loopObserver', timeout: number, observer: LoopObserver): void<sup>12+</sup> | 注册主线程消息处理耗时监听器,当系统监测到应用主线程事件处理超时时会回调该监听。<br/>只能在主线程调用,多次注册后,后一次的注册会覆盖前一次的。  |
25| off(type: 'loopObserver', observer?: LoopObserver): void<sup>12+</sup> | 以LoopObserver的形式解除应用主线程消息处理耗时监听。  |
26| on(type: 'freeze', observer: FreezeObserver): void<sup>18+</sup> | 注册应用主线程freeze监听。只能在主线程调用,多次注册后,后一次的注册会覆盖前一次的。  |
27| off(type: 'freeze', observer?: FreezeObserver): void<sup>18+</sup> | 以FreezeObserver的形式解除应用主线程消息处理耗时监听。  |
28
29当采用callback作为异步回调时,可以在callback中进行下一步处理。当采用Promise对象返回时,可以在Promise对象中类似地处理接口返回值。具体结果码说明见[解除注册结果码](#解除注册结果码)。
30
31**错误监听(ErrorObserver)接口功能介绍:**
32
33| 接口名称                         | 说明                                                         |
34| ------------------------------ | ------------------------------------------------------------ |
35| onUnhandledException(errMsg: string): void | 系统回调接口,应用注册后,当应用产生未捕获的异常时的回调。 |
36| onException?(errObject: Error): void | 系统回调接口,应用注册后,当应用产生异常上报js层时的回调。 |
37
38**应用主线程监听(LoopObserver)接口功能介绍:**
39
40| 接口名称                         | 说明                                                         |
41| ------------------------------ | ------------------------------------------------------------ |
42| onLoopTimeOut?(timeout: number): void<sup>12+</sup> | 系统回调接口,应用注册后,当应用主线程处理事件超时的回调。 |
43
44### 解除注册结果码
45
46| 结果码 | 原因                        |
47| ------ | ---------------------------  |
48| 0      |  正常返回。                          |
49| -1     | 传入的number不存在。              |
50| -2     | 参数错误。       |
51
52## 开发示例
53
54> **注意:**
55>
56> 建议在异常回调函数处理的最后,增加同步退出操作,否则可能出现多次异常回调的现象。
57
58### 单线程监听场景
59
60```ts
61import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
62import { window } from '@kit.ArkUI';
63import process from '@ohos.process';
64
65let registerId = -1;
66let callback: errorManager.ErrorObserver = {
67    onUnhandledException: (errMsg) => {
68        console.info(errMsg);
69    },
70    onException: (errorObj) => {
71        console.info('onException, name: ', errorObj.name);
72        console.info('onException, message: ', errorObj.message);
73        if (typeof(errorObj.stack) === 'string') {
74            console.info('onException, stack: ', errorObj.stack);
75        }
76        //回调函数执行完,采用同步退出方式,避免多次触发异常
77        let pro = new process.ProcessManager();
78        pro.exit(0);
79    }
80}
81
82let abilityWant: Want;
83
84export default class EntryAbility extends UIAbility {
85    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
86        console.info("[Demo] EntryAbility onCreate");
87        registerId = errorManager.on("error", callback);
88        abilityWant = want;
89    }
90
91    onDestroy() {
92        console.info("[Demo] EntryAbility onDestroy");
93        errorManager.off("error", registerId, (result) => {
94            console.info("[Demo] result " + result.code + ";" + result.message);
95        });
96    }
97
98    onWindowStageCreate(windowStage: window.WindowStage) {
99        // Main window is created, set main page for this ability
100        console.info("[Demo] EntryAbility onWindowStageCreate");
101
102        windowStage.loadContent("pages/index", (err, data) => {
103            if (err.code) {
104                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
105                return;
106            }
107            console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
108        });
109    }
110
111    onWindowStageDestroy() {
112        // Main window is destroyed, release UI related resources
113        console.info("[Demo] EntryAbility onWindowStageDestroy");
114    }
115
116    onForeground() {
117        // Ability has brought to foreground
118        console.info("[Demo] EntryAbility onForeground");
119    }
120
121    onBackground() {
122        // Ability has back to background
123        console.info("[Demo] EntryAbility onBackground");
124    }
125};
126```
127
128### 进程监听异常场景
129
130```ts
131import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
132import { window } from '@kit.ArkUI';
133import process from '@ohos.process';
134
135function errorFunc(observer: errorManager.GlobalError) {
136    console.info("[Demo] result name :" + observer.name);
137    console.info("[Demo] result message :" + observer.message);
138    console.info("[Demo] result stack :" + observer.stack);
139    console.info("[Demo] result instanceName :" + observer.instanceName);
140    console.info("[Demo] result instaceType :" + observer.instanceType);
141    //回调函数执行完,采用同步退出方式,避免多次触发异常
142    let pro = new process.ProcessManager();
143    pro.exit(0);
144}
145
146let abilityWant: Want;
147
148export default class EntryAbility extends UIAbility {
149    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
150        console.info("[Demo] EntryAbility onCreate");
151        errorManager.on("globalErrorOccurred", errorFunc);
152        abilityWant = want;
153    }
154
155    onDestroy() {
156        console.info("[Demo] EntryAbility onDestroy");
157        errorManager.off("globalErrorOccurred", errorFunc);
158    }
159
160    onWindowStageCreate(windowStage: window.WindowStage) {
161        // Main window is created, set main page for this ability
162        console.info("[Demo] EntryAbility onWindowStageCreate");
163
164        windowStage.loadContent("pages/index", (err, data) => {
165            if (err.code) {
166                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
167                return;
168            }
169            console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
170        });
171    }
172
173    onWindowStageDestroy() {
174        // Main window is destroyed, release UI related resources
175        console.info("[Demo] EntryAbility onWindowStageDestroy");
176    }
177
178    onForeground() {
179        // Ability has brought to foreground
180        console.info("[Demo] EntryAbility onForeground");
181    }
182
183    onBackground() {
184        // Ability has back to background
185        console.info("[Demo] EntryAbility onBackground");
186    }
187};
188```
189
190### 进程监听promise异常场景
191
192```ts
193import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
194import { window } from '@kit.ArkUI';
195import process from '@ohos.process';
196
197function promiseFunc(observer: errorManager.GlobalError) {
198    console.info("[Demo] result name :" + observer.name);
199    console.info("[Demo] result message :" + observer.message);
200    console.info("[Demo] result stack :" + observer.stack);
201    console.info("[Demo] result instanceName :" + observer.instanceName);
202    console.info("[Demo] result instaceType :" + observer.instanceType);
203    //回调函数执行完,采用同步退出方式,避免多次触发异常
204    let pro = new process.ProcessManager();
205    pro.exit(0);
206}
207
208
209let abilityWant: Want;
210
211export default class EntryAbility extends UIAbility {
212    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
213        console.info("[Demo] EntryAbility onCreate");
214        errorManager.on("globalUnhandledRejectionDetected", promiseFunc);
215        abilityWant = want;
216    }
217
218    onDestroy() {
219        console.info("[Demo] EntryAbility onDestroy");
220        errorManager.off("globalUnhandledRejectionDetected", promiseFunc);
221    }
222
223    onWindowStageCreate(windowStage: window.WindowStage) {
224        // Main window is created, set main page for this ability
225        console.info("[Demo] EntryAbility onWindowStageCreate");
226
227        windowStage.loadContent("pages/index", (err, data) => {
228            if (err.code) {
229                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
230                return;
231            }
232            console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
233        });
234    }
235
236    onWindowStageDestroy() {
237        // Main window is destroyed, release UI related resources
238        console.info("[Demo] EntryAbility onWindowStageDestroy");
239    }
240
241    onForeground() {
242        // Ability has brought to foreground
243        console.info("[Demo] EntryAbility onForeground");
244    }
245
246    onBackground() {
247        // Ability has back to background
248        console.info("[Demo] EntryAbility onBackground");
249    }
250};
251```
252
253### 主线程监听freeze
254
255```ts
256import { AbilityConstant, errorManager, UIAbility, Want } from '@kit.AbilityKit';
257import { window } from '@kit.ArkUI';
258import process from '@ohos.process';
259
260// Define freezeCallback
261function freezeCallback() {
262    console.info("freezecallback");
263}
264
265
266let abilityWant: Want;
267
268export default class EntryAbility extends UIAbility {
269    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
270        console.info("[Demo] EntryAbility onCreate");
271        errorManager.on("freeze", freezeCallback);
272        abilityWant = want;
273    }
274
275    onDestroy() {
276        console.info("[Demo] EntryAbility onDestroy");
277        errorManager.off("freeze", freezeCallback);
278    }
279
280    onWindowStageCreate(windowStage: window.WindowStage) {
281        // Main window is created, set main page for this ability
282        console.info("[Demo] EntryAbility onWindowStageCreate");
283
284        windowStage.loadContent("pages/index", (err, data) => {
285            if (err.code) {
286                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
287                return;
288            }
289            console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data));
290        });
291    }
292
293    onWindowStageDestroy() {
294        // Main window is destroyed, release UI related resources
295        console.info("[Demo] EntryAbility onWindowStageDestroy");
296    }
297
298    onForeground() {
299        // Ability has brought to foreground
300        console.info("[Demo] EntryAbility onForeground");
301    }
302
303    onBackground() {
304        // Ability has back to background
305        console.info("[Demo] EntryAbility onBackground");
306    }
307};
308```