You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:55:03