Expo MediaLibrary未处理Promise拒绝:无法获取相册列表
解决Expo MediaLibrary.getAlbumsAsync()的Promise拒绝错误问题
我看了你的代码和遇到的错误,问题主要出在async/await和.then/.catch的混用,以及权限判断后的逻辑分支处理不当,这确实是导致Promise拒绝错误和无法获取相册信息的核心原因,咱们一步步来修复:
问题分析
- 权限校验逻辑漏洞:你在获取权限后,只在
status !== 'granted'时做了提示,但没有在权限通过的分支里才执行相册获取操作——也就是说,哪怕用户没给权限,代码还是会去调用MediaLibrary.getAlbumsAsync(),这必然会触发权限相关的Promise拒绝。 - async/await与.then的错误混用:你用了
await来等待getAlbumsAsync(),但又链式调用了.then(),而且.then()里没有返回值,导致albumList最终是undefined。更关键的是,这种混用会让await无法正确捕获方法抛出的错误,而你的.catch()只能捕获.then()链里的异常,漏掉了getAlbumsAsync()本身的错误。
修正后的代码
import React from 'react'; import { ActivityIndicator, Button, Clipboard, Image, Share, StatusBar, StyleSheet, Text, TouchableOpacity, View, Alert, } from 'react-native'; import Expo, { MediaLibrary, Permissions, Constants, ImagePicker, registerRootComponent } from 'expo'; export default class ChoosePhotos extends React.Component { state = { image: null, uploading: false, cameraRollPerm: true, // 初始设为true,权限拒绝后再改为false albumList: [] // 新增状态存储相册列表 }; //Get Permission and get Albums list async componentDidMount(){ await this.getAlbum(); // 加await确保组件挂载时完成权限和相册获取 } getAlbum = async () => { try { const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); if(status !== 'granted'){ this.setState({ cameraRollPerm: false }); Alert.alert( '', 'Please grant permissions to access your media library to continue.', [ {text: 'OK', onPress: () => console.log('OK Pressed')}, ], { cancelable: false } ); return; // 权限拒绝时直接返回,不执行后续相册获取逻辑 } // 权限通过后才获取相册 const albumArray = await MediaLibrary.getAlbumsAsync(); console.log('获取到的相册列表:', albumArray); this.setState({ albumList: albumArray }); // 把相册列表存到状态里 } catch (error) { console.log("获取相册失败:", error); Alert.alert('错误', '无法获取你的相册,请检查权限后重试'); } } render() { console.log(this.state.image) let { image, albumList } = this.state; return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text style={{ fontSize: 20, marginBottom: 20, textAlign: 'center', marginHorizontal: 15, }}> Example: Upload ImagePicker result </Text> {/* 可在这里添加相册列表展示 */} {albumList.length > 0 && ( <View style={{marginVertical:20}}> <Text>你的相册:</Text> {albumList.map(album => ( <Text key={album.id}>{album.title}</Text> ))} </View> )} <Button onPress={this._pickImage} title="Pick an image from camera roll" /> <Button onPress={this._takePhoto} title="Take a photo" /> <StatusBar barStyle="default" /> </View> ); } _takePhoto = async () => { let pickerResult = await ImagePicker.launchCameraAsync({ }); this.props.navigation.navigate('SizeSelectionScreen', {imageLink: pickerResult.uri}); }; _pickImage = async () => { let pickerResult = await ImagePicker.launchImageLibraryAsync({ }); this.props.navigation.navigate('SizeSelectionScreen', {imageLink: pickerResult.uri}); }; }
关键修改点
- 用
try/catch包裹整个异步逻辑,统一捕获权限请求和相册获取过程中的所有错误,避免Promise拒绝未被处理的问题。 - 权限拒绝时添加
return,终止后续代码执行,防止无权限时调用相册接口。 - 去掉冗余的
.then(),改用纯async/await写法,让代码更清晰,同时确保能正确获取相册数组并存储到组件状态中。 - 新增
albumList状态来存储相册数据,方便在render里展示。
这样调整后,你应该就能正常获取相册列表,也不会再出现Promise拒绝的错误了。
内容的提问来源于stack exchange,提问作者Abrar A.
相关产品推荐
相关产品推荐

