react-native + Expo fails with Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_this.camera.takePictureAsync')
react-native + Expo fails with Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_this.camera.takePictureAsync')
我正在使用 react-native v0.63 和 Expo SDK 38 进行开发。我的目标是读取 android 或 ios phone 和 select 图片然后将这些图片故事化成一个数组,显示在手机屏幕上。我通过研究发现 Expo SDK 38 不支持 react-native cameraroll,必须使用 expo-media-library 来实现这些功能。作为测试,我从研究中提取了一些代码,这些代码要求获得访问相机和相机胶卷的权限。没关系。然后我调用 this.camera.takePictureAsync() 看看我是否可以访问相机拍照。简单的测试。那就是我得到错误的地方:未处理的承诺拒绝:TypeError:undefined is not an object (evaluating '_this.camera.takePictureAsync')
这是我的设置:
完整的错误是:
WARNING
18:17
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_this.camera.takePictureAsync')]
Stack trace:
node_modules\react-navigation\node_modules\@react-navigation\native\lib\module\createNavigationAwareScrollable.js:105:6 in NavigationAwareScrollable#render
node_modules\regenerator-runtime\runtime.js:45:36 in tryCatch
node_modules\regenerator-runtime\runtime.js:274:29 in invoke
node_modules\regenerator-runtime\runtime.js:45:36 in tryCatch
node_modules\regenerator-runtime\runtime.js:135:27 in invoke
node_modules\regenerator-runtime\runtime.js:170:16 in PromiseImpl$argument_0
node_modules\promise\setimmediate\core.js:45:6 in tryCallTwo
node_modules\promise\setimmediate\core.js:200:22 in doResolve
node_modules\promise\setimmediate\core.js:66:11 in Promise
node_modules\regenerator-runtime\runtime.js:169:15 in callInvokeWithMethodAndArg
node_modules\regenerator-runtime\runtime.js:192:38 in enqueue
node_modules\regenerator-runtime\runtime.js:219:8 in exports.async
http://192.168.0.27:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:253923:41 in _callee
http://192.168.0.27:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:254521:108 in onPress
node_modules\react-native\Libraries\Components\Touchable\TouchableNativeFeedback.js:169:10 in Pressability$argument_0.onPress
node_modules\react-native\Libraries\Pressability\Pressability.js:655:17 in _performTransitionSideEffects
node_modules\react-native\Libraries\Pressability\Pressability.js:589:6 in _receiveSignal
node_modules\react-native\Libraries\Pressability\Pressability.js:499:8 in responderEventHandlers.onResponderRelease
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:286:4 in invokeGuardedCallbackImpl
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:497:2 in invokeGuardedCallback
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:521:2 in invokeGuardedCallbackAndCatchFirstError
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:683:41 in executeDispatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:707:19 in executeDispatchesInOrder
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:872:28 in executeDispatchesAndRelease
[native code]:null in forEach
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:851:4 in forEachAccumulated
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:897:20 in runEventsInBatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:1069:18 in runExtractedPluginEventsInBatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2835:35 in batchedUpdates$argument_0
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:20569:13 in batchedUpdates
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2731:29 in batchedUpdates
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2834:16 in _receiveRootNodeIDEvent
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2911:27 in receiveTouches
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:425:19 in __callFunction
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112:6 in __guard$argument_0
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:373:10 in __guard
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:4 in callFunctionReturnFlushedQueue
[native code]:null in callFunctionReturnFlushedQueue
...
我的进口商品:
import React, { Component } from "react";
import styles from "./styles";
import { Platform, Image, ImageBackground, TextInput, TouchableWithoutFeedback, TouchableOpacity, Dimensions, FlatList, SafeAreaView,TouchableHighlight, View as RNView, Text, Alert } from "react-native";
import {Container, Grid, Col, Row, Header, Content, Item, Input, View, List, ListItem, Textarea, Button, Form, Accordion, Left, Right, Body,Thumbnail, Icon, Title, Spinner, Picker, DatePicker, } from 'native-base';
import { Ionicons } from '@expo/vector-icons';
import { FlatGrid } from 'react-native-super-grid';
import {Image as SVGImage} from "react-native-svg";
import Fire from '../Fire';
import firebase from 'firebase';
import * as ImagePicker from 'expo-image-picker';
// import * as Permissions from 'expo-permissions';
import Expo, { Constants, } from 'expo';
import * as MediaLibrary from 'expo-media-library';
import * as Permissions from 'expo-permissions';
import { Camera } from 'expo-camera';
获取权限我调用:
async componentDidMount() {
this.getCameraPermissions();
}
async getCameraPermissions() {
console.log('getCameraPermissions: enter function');
const { status } = await Permissions.askAsync(Permissions.CAMERA);
if (status === 'granted') {
console.log("getCameraPermissions: status = "+status);
this.setState({ cameraGranted: true });
} else {
this.setState({ cameraGranted: false });
console.log('Uh oh! The user has not granted us permission.');
}
this.getCameraRollPermissions();
}
async getCameraRollPermissions() {
console.log("getCameraRollPermissions: Enter Function");
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status === 'granted') {
console.log("getCameraRollPermissions: status = "+status);
this.setState({ rollGranted: true });
} else {
console.log('Uh oh! The user has not granted us permission.');
this.setState({ rollGranted: false });
}
}
这是抛出错误的函数调用。您可以通过控制台日志看到它进入函数并死于 takepictureasync()
takePictureAndCreateAlbum = async () => {
console.log('takePictureCreateAlbum: Entering function');
const { uri } = await this.camera.takePictureAsync()
.then(() => {
Alert.alert('takePictureCreateAlbum: taking picture')
})
.catch(error => {
Alert.alert('takePictureCreateAlbum Error!');
});
console.log('takePictureCreateAlbum: uri', uri);
const asset = await MediaLibrary.createAssetAsync(uri);
console.log('asset', asset);
MediaLibrary.createAlbumAsync('Expo', asset)
.then(() => {
Alert.alert('Album created!')
})
.catch(error => {
Alert.alert('An Error Occurred!')
});
};
作为测试,我通过此处的按钮调用它:
<Button
style={{flex: 1, justifyContent: "flex-start", backgroundColor: "lightgrey", marginRight: 5}}
onPress={() =>
this.state.rollGranted && this.state.cameraGranted
? this.takePictureAndCreateAlbum()
: Alert.alert('Permissions not granted')
// this.switchToStories();
}
>
我正在模拟的 android 设备和真实的 android 设备三星 S7 上进行测试。两者都会产生错误。
我以为我可以捕获错误但失败了。我还尝试从调用中返回所有值,而不仅仅是 uri 并且它的行为相同。想法?
好的,我希望这能帮助其他落入这个陷阱的人。这个错误归结为真正理解 .then .catch 错误 handling.I 需要在 .then()
中对 uri 执行任何功能
可以在这里阅读一篇很棒的短文,让我继续前进:
https://medium.com/@lucymarmitchell/using-then-catch-finally-to-handle-errors-in-javascript-promises-6de92bce3afc
还有我调用的相机功能错了:
const { uri } = await this.camera.takePictureAsync()
.then(() => {
Alert.alert('takePictureCreateAlbum: taking picture')
})
.catch(error => {
Alert.alert('takePictureCreateAlbum Error!');
});
需要从 this.camera.takePictureAsync() 中删除 this。
我正在使用 react-native v0.63 和 Expo SDK 38 进行开发。我的目标是读取 android 或 ios phone 和 select 图片然后将这些图片故事化成一个数组,显示在手机屏幕上。我通过研究发现 Expo SDK 38 不支持 react-native cameraroll,必须使用 expo-media-library 来实现这些功能。作为测试,我从研究中提取了一些代码,这些代码要求获得访问相机和相机胶卷的权限。没关系。然后我调用 this.camera.takePictureAsync() 看看我是否可以访问相机拍照。简单的测试。那就是我得到错误的地方:未处理的承诺拒绝:TypeError:undefined is not an object (evaluating '_this.camera.takePictureAsync')
这是我的设置: 完整的错误是:
WARNING
18:17
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_this.camera.takePictureAsync')]
Stack trace:
node_modules\react-navigation\node_modules\@react-navigation\native\lib\module\createNavigationAwareScrollable.js:105:6 in NavigationAwareScrollable#render
node_modules\regenerator-runtime\runtime.js:45:36 in tryCatch
node_modules\regenerator-runtime\runtime.js:274:29 in invoke
node_modules\regenerator-runtime\runtime.js:45:36 in tryCatch
node_modules\regenerator-runtime\runtime.js:135:27 in invoke
node_modules\regenerator-runtime\runtime.js:170:16 in PromiseImpl$argument_0
node_modules\promise\setimmediate\core.js:45:6 in tryCallTwo
node_modules\promise\setimmediate\core.js:200:22 in doResolve
node_modules\promise\setimmediate\core.js:66:11 in Promise
node_modules\regenerator-runtime\runtime.js:169:15 in callInvokeWithMethodAndArg
node_modules\regenerator-runtime\runtime.js:192:38 in enqueue
node_modules\regenerator-runtime\runtime.js:219:8 in exports.async
http://192.168.0.27:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:253923:41 in _callee
http://192.168.0.27:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&minify=false&hot=false:254521:108 in onPress
node_modules\react-native\Libraries\Components\Touchable\TouchableNativeFeedback.js:169:10 in Pressability$argument_0.onPress
node_modules\react-native\Libraries\Pressability\Pressability.js:655:17 in _performTransitionSideEffects
node_modules\react-native\Libraries\Pressability\Pressability.js:589:6 in _receiveSignal
node_modules\react-native\Libraries\Pressability\Pressability.js:499:8 in responderEventHandlers.onResponderRelease
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:286:4 in invokeGuardedCallbackImpl
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:497:2 in invokeGuardedCallback
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:521:2 in invokeGuardedCallbackAndCatchFirstError
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:683:41 in executeDispatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:707:19 in executeDispatchesInOrder
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:872:28 in executeDispatchesAndRelease
[native code]:null in forEach
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:851:4 in forEachAccumulated
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:897:20 in runEventsInBatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:1069:18 in runExtractedPluginEventsInBatch
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2835:35 in batchedUpdates$argument_0
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:20569:13 in batchedUpdates
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2731:29 in batchedUpdates
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2834:16 in _receiveRootNodeIDEvent
node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2911:27 in receiveTouches
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:425:19 in __callFunction
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112:6 in __guard$argument_0
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:373:10 in __guard
node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:4 in callFunctionReturnFlushedQueue
[native code]:null in callFunctionReturnFlushedQueue
...
我的进口商品:
import React, { Component } from "react";
import styles from "./styles";
import { Platform, Image, ImageBackground, TextInput, TouchableWithoutFeedback, TouchableOpacity, Dimensions, FlatList, SafeAreaView,TouchableHighlight, View as RNView, Text, Alert } from "react-native";
import {Container, Grid, Col, Row, Header, Content, Item, Input, View, List, ListItem, Textarea, Button, Form, Accordion, Left, Right, Body,Thumbnail, Icon, Title, Spinner, Picker, DatePicker, } from 'native-base';
import { Ionicons } from '@expo/vector-icons';
import { FlatGrid } from 'react-native-super-grid';
import {Image as SVGImage} from "react-native-svg";
import Fire from '../Fire';
import firebase from 'firebase';
import * as ImagePicker from 'expo-image-picker';
// import * as Permissions from 'expo-permissions';
import Expo, { Constants, } from 'expo';
import * as MediaLibrary from 'expo-media-library';
import * as Permissions from 'expo-permissions';
import { Camera } from 'expo-camera';
获取权限我调用:
async componentDidMount() {
this.getCameraPermissions();
}
async getCameraPermissions() {
console.log('getCameraPermissions: enter function');
const { status } = await Permissions.askAsync(Permissions.CAMERA);
if (status === 'granted') {
console.log("getCameraPermissions: status = "+status);
this.setState({ cameraGranted: true });
} else {
this.setState({ cameraGranted: false });
console.log('Uh oh! The user has not granted us permission.');
}
this.getCameraRollPermissions();
}
async getCameraRollPermissions() {
console.log("getCameraRollPermissions: Enter Function");
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status === 'granted') {
console.log("getCameraRollPermissions: status = "+status);
this.setState({ rollGranted: true });
} else {
console.log('Uh oh! The user has not granted us permission.');
this.setState({ rollGranted: false });
}
}
这是抛出错误的函数调用。您可以通过控制台日志看到它进入函数并死于 takepictureasync()
takePictureAndCreateAlbum = async () => {
console.log('takePictureCreateAlbum: Entering function');
const { uri } = await this.camera.takePictureAsync()
.then(() => {
Alert.alert('takePictureCreateAlbum: taking picture')
})
.catch(error => {
Alert.alert('takePictureCreateAlbum Error!');
});
console.log('takePictureCreateAlbum: uri', uri);
const asset = await MediaLibrary.createAssetAsync(uri);
console.log('asset', asset);
MediaLibrary.createAlbumAsync('Expo', asset)
.then(() => {
Alert.alert('Album created!')
})
.catch(error => {
Alert.alert('An Error Occurred!')
});
};
作为测试,我通过此处的按钮调用它:
<Button
style={{flex: 1, justifyContent: "flex-start", backgroundColor: "lightgrey", marginRight: 5}}
onPress={() =>
this.state.rollGranted && this.state.cameraGranted
? this.takePictureAndCreateAlbum()
: Alert.alert('Permissions not granted')
// this.switchToStories();
}
>
我正在模拟的 android 设备和真实的 android 设备三星 S7 上进行测试。两者都会产生错误。
我以为我可以捕获错误但失败了。我还尝试从调用中返回所有值,而不仅仅是 uri 并且它的行为相同。想法?
好的,我希望这能帮助其他落入这个陷阱的人。这个错误归结为真正理解 .then .catch 错误 handling.I 需要在 .then()
中对 uri 执行任何功能可以在这里阅读一篇很棒的短文,让我继续前进: https://medium.com/@lucymarmitchell/using-then-catch-finally-to-handle-errors-in-javascript-promises-6de92bce3afc
还有我调用的相机功能错了:
const { uri } = await this.camera.takePictureAsync()
.then(() => {
Alert.alert('takePictureCreateAlbum: taking picture')
})
.catch(error => {
Alert.alert('takePictureCreateAlbum Error!');
});
需要从 this.camera.takePictureAsync() 中删除 this。