React Native集成TensorFlow报错求助:附App.js代码及报错信息
Expo + React Native + TensorFlow.js 未处理Promise拒绝错误解决
问题描述
在使用Expo与React Native集成TensorFlow.js时,出现未处理的Promise拒绝错误:TypeError: undefined is not a function,推测错误来自模型加载代码const model = await tf.loadLayersModel(bundleResourceIO(modelJson, modelWeights))以及图像张量处理代码const imageTensor = images.next().value.expandDims(0).div(127.5).sub(1)。以下是完整的App.js代码:
//expo & react import * as React from 'react'; import { Dimensions, StyleSheet, View } from 'react-native'; import { Camera, CameraType } from 'expo-camera'; //tensorflow import * as tf from '@tensorflow/tfjs'; import { bundleResourceIO, cameraWithTensors, } from '@tensorflow/tfjs-react-native'; import Loading from './Loading'; const TensorCamera = cameraWithTensors(Camera); const OUTPUT_TENSOR_WIDTH = 270; const OUTPUT_TENSOR_HEIGHT = 480; const CAM_PREVIEW_WIDTH = Dimensions.get('window').width; const CAM_PREVIEW_HEIGHT = CAM_PREVIEW_WIDTH / (9 / 16); export default function App() { const [tfReady, setTfReady] = React.useState(false); const [model, setModel] = React.useState(); const rafId = React.useRef(null); React.useEffect(() => { const prepare = async () => { rafId.current = null; await Camera.requestCameraPermissionsAsync(); await tf.ready(); const modelJson = require('./model/model.json'); const modelWeights = require('./model/weights.bin'); const model = await tf.loadLayersModel( bundleResourceIO(modelJson, modelWeights) ); setModel(model); setTfReady(true); }; prepare(); }, []); React.useEffect(() => { return () => { if (rafId.current != null && rafId.current != 0) { cancelAnimationFrame(rafId.current); rafId.current = 0; } }; }, []); const handleCameraStream = async (images, updatePreview, gl) => { const loop = () => { if (rafId.current === 0) { return; } tf.tidy(() => { const imageTensor = images.next().value.expandDims(0).div(127.5).sub(1); const f = (OUTPUT_TENSOR_HEIGHT - OUTPUT_TENSOR_WIDTH) / 2 / OUTPUT_TENSOR_HEIGHT; const cropped = tf.image.cropAndResize( imageTensor, tf.tensor2d([f, 0, 1 - f, 1], [1, 4]), [0], [224, 224] ); }); rafId.current = requestAnimationFrame(loop); }; loop(); console.log(images); }; if (!tfReady) { return <Loading />; } else { return ( <View style={styles.container}> <TensorCamera style={styles.camera} autorender={true} type={CameraType.back} resizeWidth={OUTPUT_TENSOR_WIDTH} resizeHeight={OUTPUT_TENSOR_HEIGHT} resizeDepth={3} onReady={handleCameraStream} /> </View> ); } } const styles = StyleSheet.create({ container: { width: CAM_PREVIEW_WIDTH, height: CAM_PREVIEW_HEIGHT, marginTop: Dimensions.get('window').height / 2 - CAM_PREVIEW_HEIGHT / 2, alignItems: 'center', justifyContent: 'center', }, camera: { width: '80%', height: '80%', zIndex: 1, }, });
报错信息
可能存在未处理的Promise拒绝(ID:5):TypeError: undefined is not a function
排查与解决步骤
1. 模型加载代码修复
- 校验模型文件路径与格式:确认
model.json中的weightsManifest字段指向正确的weights.bin路径,本地文件导入时require('./model/weights.bin')路径无误。路径错误会导致模型加载失败,引发后续函数未定义异常。 - 版本兼容性检查:确保
@tensorflow/tfjs与@tensorflow/tfjs-react-native版本匹配,建议安装稳定兼容版本(例如@tensorflow/tfjs@4.14.0搭配@tensorflow/tfjs-react-native@0.8.0),版本不匹配会导致API不一致,比如bundleResourceIO函数不存在或参数错误。
2. 图像张量处理代码修复
- 正确处理异步迭代器:
images是异步迭代器,不能同步调用next(),需使用await images.next()获取张量,否则可能拿到undefined,导致后续张量操作报错。修改handleCameraStream函数:
const handleCameraStream = async (images, updatePreview, gl) => { const loop = async () => { if (rafId.current === 0) { return; } try { const imageResult = await images.next(); // 若迭代完成或无有效张量,跳过当前循环 if (imageResult.done || !imageResult.value) { rafId.current = requestAnimationFrame(loop); return; } tf.tidy(() => { const imageTensor = imageResult.value.expandDims(0).div(127.5).sub(1); const f = (OUTPUT_TENSOR_HEIGHT - OUTPUT_TENSOR_WIDTH) / 2 / OUTPUT_TENSOR_HEIGHT; const cropped = tf.image.cropAndResize( imageTensor, tf.tensor2d([f, 0, 1 - f, 1], [1, 4]), [0], [224, 224] ); // 此处可添加模型预测逻辑:model.predict(cropped) }); } catch (err) { console.error('相机流处理错误:', err); } rafId.current = requestAnimationFrame(loop); }; loop(); };
3. 其他潜在问题修复
- 相机权限校验:在
prepare函数中添加权限状态校验,确保相机权限已授予,避免相机流无法初始化:
const prepare = async () => { rafId.current = null; const { status } = await Camera.requestCameraPermissionsAsync(); if (status !== 'granted') { alert('需要授予相机权限才能继续'); return; } await tf.ready(); // 后续模型加载代码... };
- 避免渲染冲突:将
TensorCamera的autorender属性设为false,避免自动渲染与手动requestAnimationFrame循环冲突,导致张量获取异常。
内容的提问来源于stack exchange,提问作者ChanHoo Kim
相关产品推荐
相关产品推荐

