跳到主要内容

错误管理开发指导

场景介绍

当应用的代码存在规范问题或错误时,会在运行中产生异常和错误,如应用未捕获异常等。在错误产生后,应用会异常退出。错误日志通常会保存在用户本地存储设备中,不方便开发者定位问题。所以,应用开发者可以使用错误管理的接口,在应用退出前,及时将相关错误及日志上报到开发者的服务平台来定位问题。

使用errorManager接口监听异常和错误后,应用不会退出,建议在回调函数执行完后,增加同步退出操作,如果只是为了获取错误日志,建议使用HiAppEvent订阅事件

接口说明

应用错误管理接口由@ohos.app.ability.errorManager (错误管理模块)提供,使用接口能力前需注册错误观测器,开发者可以通过import引入,详见开发示例

错误管理接口功能介绍

接口名称说明
on(type: "error", observer: ErrorObserver): number注册错误监听接口,当系统监测到应用异常时会回调该监听。该接口为同步接口,返回值为注册的监听对象对应的序号。
off(type: "error", observerId: number, callback: AsyncCallback<void>): void以callback的形式解除注册监听,传入的number为之前注册监听时返回的序号。
off(type: "error", observerId: number): Promise<void>以Promise的形式解除注册监听,传入的number为之前注册监听时返回的序号。
on(type: 'globalErrorOccurred', observer: GlobalObserver): void注册进程错误监听接口,当系统监测到应用异常时会回调该监听,该接口为同步接口,即一次注册,全局监听。(推荐使用) 说明:从API version 18开始,支持该接口。
off(type: 'globalErrorOccurred', observer?: GlobalObserver): void以callback的形式解除注册监听。(推荐使用) 说明:从API version 18开始,支持该接口。
on(type: 'globalUnhandledRejectionDetected', observer: GlobalObserver): void注册进程错误监听接口,当系统监测到应用promise异常时会回调该监听,该接口为同步接口,即一次注册,全局监听。(推荐使用) 说明:从API version 18开始,支持该接口。
off(type: 'globalUnhandledRejectionDetected', observer?: GlobalObserver): void以callback的形式解除注册监听。(推荐使用) 说明:从API version 18开始,支持该接口。
on(type: 'loopObserver', timeout: number, observer: LoopObserver): void注册主线程消息处理耗时监听器,当系统监测到应用主线程事件处理超时时会回调该监听。 只能在主线程调用,多次注册后,后一次的注册会覆盖前一次的。
off(type: 'loopObserver', observer?: LoopObserver): void以LoopObserver的形式解除应用主线程消息处理耗时监听。
on(type: 'freeze', observer: FreezeObserver): void注册应用主线程freeze监听。只能在主线程调用,重复注册后,后一次的注册会覆盖前一次的。
off(type: 'freeze', observer?: FreezeObserver): void以FreezeObserver的形式解除应用主线程消息处理耗时监听。 说明:从API version 18开始,支持该接口。
setDefaultErrorHandler(defaultHandler?: ErrorHandler): ErrorHandler仅允许在主线程调用,发生JS_CRASH异常时,支持链式回调,返回值为上一次注册的处理器。 说明:从API version 21开始,支持该接口。

当采用callback作为异步回调时,可以在callback中进行下一步处理。

当采用Promise对象返回时,可以在Promise对象中类似地处理接口返回值,具体结果码说明见解除注册结果码

错误监听(ErrorObserver)接口功能介绍

接口名称说明
onUnhandledException(errMsg: string): void系统回调接口,应用注册后,当应用产生未捕获的异常时的回调。
onException?(errObject: Error): void系统回调接口,应用注册后,当应用产生异常上报js层时的回调。

应用主线程监听(LoopObserver)接口功能介绍

接口名称说明
onLoopTimeOut?(timeout: number): void系统回调接口,应用注册后,当应用主线程处理事件超时的回调。

解除注册结果码

结果码原因
0正常返回
-1传入的number参数不存在
-2参数错误

开发示例

建议在异常回调函数处理的最后,增加同步退出操作,以避免多次异常回调。

单线程监听场景

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

let observer: errorManager.ErrorObserver = {
onUnhandledException(errorMsg) {
console.error('testErrorManage','onUnhandledException, errorMsg: ', errorMsg);
},
onException(errorObj) {
console.error('testErrorManage','onException, name: ', errorObj.name);
console.error('testErrorManage','onException, message: ', errorObj.message);
if (typeof(errorObj.stack) === 'string') {
console.error('testErrorManage','onException, stack: ', errorObj.stack);
}
}
};

新增触发按钮。

Button('单线程监听场景').onClick(()=>{
let observerId = -1;
try {
observerId = errorManager.on('error', observer);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
throw new Error('test errorObserver msg');
}).position({x:50, y:50});

进程监听异常场景

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

function errorFunc(observer: errorManager.GlobalError) {
console.error('testErrorManage','result name :' + observer.name);
console.error('testErrorManage','result message :' + observer.message);
console.error('testErrorManage','result stack :' + observer.stack);
console.error('testErrorManage','result instanceName :' + observer.instanceName);
console.error('testErrorManage','result instanceType :' + observer.instanceType);
};

新增触发按钮。

Button('进程监听异常场景').onClick(()=>{
try {
errorManager.on('globalErrorOccurred', errorFunc);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
throw new Error('test errorFunc msg');
}).position({x:50, y:100});

进程监听promise异常场景

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

function promiseFunc(observer: errorManager.GlobalError) {
console.error('testErrorManage','result name :' + observer.name);
console.error('testErrorManage','result message :' + observer.message);
console.error('testErrorManage','result stack :' + observer.stack);
console.error('testErrorManage','result instanceName :' + observer.instanceName);
console.error('testErrorManage','result instanceType :' + observer.instanceType);
};

async function promiseFuncOne() {
throw new Error('process promise exception');
};

新增触发按钮。

Button('进程监听promise异常场景').onClick(()=>{
try {
errorManager.on('globalUnhandledRejectionDetected', promiseFunc);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
new Promise<string>(() => {
promiseFuncOne();
}).then(() => {
throw new Error('test promiseFuncOne msg');
});
}).position({x:50, y:200});

主线程监听freeze

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

function freezeCallback() {
console.error('testErrorManage','freezecallback');
};

新增触发按钮。

Button('主线程监听freeze').onClick(()=>{
try {
errorManager.on('freeze', freezeCallback);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
let date = Date.now();
while (Date.now() - date < 15000) {
};
}).position({x:50, y:300});

主线程监听消息处理耗时

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

let loopObserver: errorManager.LoopObserver = {
onLoopTimeOut(timeout: number) {
console.error('testErrorManage','Duration timeout: ' + timeout);
}
};

新增触发按钮。

Button('主线程监听消息处理耗时').onClick(()=>{
try {
errorManager.on('loopObserver', 1, loopObserver);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
let date = Date.now();
while (Date.now() - date < 4000) {
};
}).position({x:50, y:150});

进程promise监听注册被拒绝

引入头文件。

import { errorManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

新增监听回调函数。

let promise1 = new Promise<void>(() => {}).then(() => {
throw new Error('uncaught error');
});

let unhandledrejectionObserver: errorManager.UnhandledRejectionObserver = (reason: Error, promise: Promise<void>) => {
if (promise === promise1) {
console.error('testErrorManage','promise1 is rejected');
}
console.error('testErrorManage','reason.name: ', reason.name);
console.error('testErrorManage','reason.message: ', reason.message);
if (reason.stack) {
console.error('testErrorManage','reason.stack: ', reason.stack);
}
};

async function promiseFuncTwo() {
throw new Error('process promise unhandled rejection exception');
};

新增触发按钮。

Button('进程promise监听注册被拒绝').onClick(()=>{
try {
errorManager.on('unhandledRejection', unhandledrejectionObserver);
} catch (paramError) {
let code = (paramError as BusinessError).code;
let message = (paramError as BusinessError).message;
console.error('testErrorManage',`error: ${code}, ${message}`);
}
// 构造场景故障
new Promise<string>(() => {
promiseFuncTwo();
}).then(() => {
throw new Error('test promiseFuncTwo msg');
});
}).position({x:50, y:250});

错误处理器责任链模式场景

定义第一个错误处理器及注册方法,无前置处理器时退出进程。

import { errorManager } from '@kit.AbilityKit';
import { process } from '@kit.ArkTS';

let firstHandler: errorManager.ErrorHandler;
const firstErrorHandler: errorManager.ErrorHandler = (reason: Error) => {
// 自定义的第一个errorHandler实现逻辑
console.info('[FirstHandler] First uncaught exception handler invoked.');
if (firstHandler) {
firstHandler(reason);
} else {
// 建议增加判空操作,如果为空采用同步退出方式
const processManager = new process.ProcessManager();
processManager.exit(0);
}
};

export function setFirstErrorHandler() {
firstHandler = errorManager.setDefaultErrorHandler(firstErrorHandler);
console.info('Registered First Error Handler');
}

定义第二个错误处理器及注册方法,形成链式调用。

import { errorManager } from '@kit.AbilityKit';
import { process } from '@kit.ArkTS';

let secondHandler: errorManager.ErrorHandler;
const secondErrorHandler: errorManager.ErrorHandler = (reason: Error) => {
// 自定义的第二个errorHandler实现逻辑
console.info('[SecondHandler] Second uncaught exception handler invoked.');
if (secondHandler) {
secondHandler(reason);
} else {
const processManager = new process.ProcessManager();
processManager.exit(0);
}
};

export function setSecondErrorHandler() {
secondHandler = errorManager.setDefaultErrorHandler(secondErrorHandler);
console.info('Registered Second Error Handler');
}

引入头文件。

import { setFirstErrorHandler } from './FirstErrorHandler';
import { setSecondErrorHandler } from './SecondErrorHandler';

新增错误处理器责任链模式构造函数。

function testErrorHandlers() {
setFirstErrorHandler();
setSecondErrorHandler();
throw new Error('Test uncaught exception!');
}

主组件通过按钮触发测试,注册两个处理器并抛错验证处理链。

Button('错误处理器责任链模式场景').onClick(()=>{
testErrorHandlers();
}).position({x:50, y:350});