React Native中react-native-exception-handler无法捕获Promise内错误
React Native中react-native-exception-handler无法捕获Promise内部错误的解决方法
问题说明
在运行于Android虚拟设备(API 23)的React Native项目中,使用react-native-exception-handler实现全局错误统一处理时,普通同步JS错误可被正常捕获并弹出自定义错误弹窗,但Promise内部抛出的错误仅会在日志中输出警告,无法触发自定义错误处理逻辑。
环境配置
- Android Gradle Plugin版本:7.2.0
- Gradle版本:7.4.2
- 项目
build.gradle核心配置:
buildscript { ext { buildToolsVersion = "31.0.0" minSdkVersion = 21 compileSdkVersion = 31 targetSdkVersion = 31 // 其他配置... } }
现有代码示例
App.js代码
import React, { Component } from 'react'; import { StyleSheet, Button, View, Alert, } from 'react-native'; import { setJSExceptionHandler } from 'react-native-exception-handler'; const errorHandler = (e, isFatal) => { if (isFatal) { Alert.alert( 'Unexpected error occurred', ` Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message} We have reported this to our team ! Please close the app and start again! `, [{ text: 'Close' }] ); } else { console.log(e); } }; setJSExceptionHandler(errorHandler, true); export default class App extends Component { constructor() { super(); } causeJSError () { throw new Error('THIS IS A CUSTOM UNHANDLED JS ERROR'); } causeJSPromiseError () { new Promise((resolve, reject) => { throw new Error("Whoops!"); }).catch(error => { throw error; }); } render() { return ( <View style={styles.container}> <Button onPress={this.causeJSError.bind(this)} title="CAUSE JS ERROR" color="#841584" style={{flex:1}}/> <Button onPress={this.causeJSPromiseError.bind(this)} title="CAUSE JS PROMISE ERROR" color="#841584" style={{flex:1}}/> </View> ); } }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, });
测试现象
- 点击「CAUSE JS ERROR」按钮:全局异常处理器正常触发,弹出自定义错误弹窗。
- 点击「CAUSE JS PROMISE ERROR」按钮:无自定义错误弹窗,仅日志输出警告:
LOG Running "handlertest" with {"rootTag":21} WARN Possible Unhandled Promise Rejection (id: 0): Error: Whoops! http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false&app=com.handlertest&modulesOnly=false&runModule=true:112203:26 // 其余调用栈日志...
解决方案
react-native-exception-handler的setJSExceptionHandler仅处理同步JS错误,Promise未处理的拒绝属于异步错误场景,需要使用专门的setUnhandledRejectionHandler方法来捕获。
修改App.js代码,添加Promise未处理拒绝的处理器:
import React, { Component } from 'react'; import { StyleSheet, Button, View, Alert, } from 'react-native'; import { setJSExceptionHandler, setUnhandledRejectionHandler } from 'react-native-exception-handler'; const errorHandler = (e, isFatal) => { if (isFatal) { Alert.alert( 'Unexpected error occurred', ` Error: ${(isFatal) ? 'Fatal:' : ''} ${e.name} ${e.message} We have reported this to our team ! Please close the app and start again! `, [{ text: 'Close' }] ); } else { console.log(e); } }; setJSExceptionHandler(errorHandler, true); // 添加Promise未处理拒绝处理器 setUnhandledRejectionHandler((reason) => { // 将Promise拒绝视为非致命错误,复用现有错误处理逻辑 errorHandler(reason, false); // 如果需要视为致命错误,可传true:errorHandler(reason, true); }); export default class App extends Component { // 其余代码保持不变... }
原理说明
Promise的未处理拒绝不会触发同步的throw错误流,而是属于单独的异步错误事件。react-native-exception-handler提供了setUnhandledRejectionHandler方法专门监听这类错误,通过注册该处理器,就能将Promise内部抛出的错误纳入全局错误处理体系中。
内容的提问来源于stack exchange,提问作者araraujo
相关产品推荐
相关产品推荐

