Expo中MailComposer.composeAsync返回Promise未定义问题求助
问题:Expo MailComposer.composeAsync返回undefined,无法链式执行文件删除操作
我在Expo Snack开发Android应用,功能流程为:从网络下载.mobi文件 → 将文件附加到邮件草稿 → 删除该.mobi文件。但根据Expo文档,MailComposer.composeAsync(options)应返回包含MailComposerStatus的Promise,实际却始终拿到undefined,导致无法链式调用.then()执行后续的文件删除操作。
原代码
import React, { useState } from 'react'; import { Text, View, StyleSheet, Alert, Button } from 'react-native'; import Constants from 'expo-constants'; import * as FileSystem from 'expo-file-system'; import * as MailComposer from 'expo-mail-composer'; export default function App() { const [stxt, setStxt] = useState("123"); return ( <View style={styles.container}> <Text style={styles.paragraph}>{stxt}</Text> <Text style={styles.paragraph}>{data}</Text> <Button title="Send" onPress={btnclicked}/> </View> ); } let data = "outside app() const text"; const btnclicked = () => { FileSystem.downloadAsync('https://filesamples.com/samples/ebook/mobi/sample1.mobi',FileSystem.documentDirectory + 'test.mobi') .then(({ uri }) => {MailComposer.composeAsync({recipients:["test@gmail.com"], attachments:[uri]}); }) .then(({ res }) => {console.log(res)} ) .catch(error => {console.error(error);}); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: Constants.statusBarHeight, backgroundColor: '#ecf0f1', padding: 8, }, paragraph: { margin: 24, fontSize: 30, fontWeight: 'bold', textAlign: 'center', }, });
问题原因
第一个.then()回调中,调用MailComposer.composeAsync()后没有返回该Promise对象,导致链式调用的下一个.then()接收到的是undefined,无法获取邮件操作状态。
修复方案
修改点:
- 在第一个
.then()中返回MailComposer.composeAsync()的Promise,让链式调用能正确获取后续的状态值 - 使用
FileSystem.deleteAsync()直接删除文件(若只需删除而非移动,比moveAsync更直接) - 根据返回的
status判断执行文件删除的时机(可根据需求调整逻辑)
修复后的代码
import React, { useState } from 'react'; import { Text, View, StyleSheet, Alert, Button } from 'react-native'; import Constants from 'expo-constants'; import * as FileSystem from 'expo-file-system'; import * as MailComposer from 'expo-mail-composer'; export default function App() { const [stxt, setStxt] = useState("123"); return ( <View style={styles.container}> <Text style={styles.paragraph}>{stxt}</Text> <Text style={styles.paragraph}>{data}</Text> <Button title="Send" onPress={btnclicked}/> </View> ); } let data = "outside app() const text"; const filePath = `${FileSystem.documentDirectory}test.mobi`; // 提取文件路径为变量,方便复用 const btnclicked = () => { FileSystem.downloadAsync('https://filesamples.com/samples/ebook/mobi/sample1.mobi', filePath) // 关键:返回MailComposer的Promise .then(({ uri }) => { return MailComposer.composeAsync({ recipients: ["test@gmail.com"], attachments: [uri] }); }) .then(({ status }) => { console.log('邮件操作状态:', status); // 无论用户操作结果如何,都删除文件(可根据需求调整,比如仅在sent/saved时删除) return FileSystem.deleteAsync(filePath); }) .then(() => { console.log('文件已成功删除'); }) .catch(error => { console.error('操作出错:', error); // 出错时也尽量清理文件 FileSystem.deleteAsync(filePath).catch(err => console.error('删除失败:', err)); }); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: Constants.statusBarHeight, backgroundColor: '#ecf0f1', padding: 8, }, paragraph: { margin: 24, fontSize: 30, fontWeight: 'bold', textAlign: 'center', }, });
说明
修复后,你可以通过status值判断邮件操作结果:
MailComposerStatus.SENT:邮件已发送MailComposerStatus.SAVED:邮件已保存为草稿MailComposerStatus.CANCELLED:用户取消了邮件操作MailComposerStatus.UNKNOWN:状态未知
你可以根据业务需求调整文件删除的触发条件,比如仅在邮件成功发送/保存后删除文件。
内容的提问来源于stack exchange,提问作者difoxy2
相关产品推荐
相关产品推荐

