React Native中如何在同步函数内顺序执行异步任务?
问题描述
我需要按特定顺序执行一系列包含异步任务的函数,要求这些函数必须顺序执行。代码需完成以下操作:
- 删除Document Directory中的当前内容(文件为持久化存储,但仅作临时使用)
- 将当前文件资源从原位置复制到Document Directory
- 压缩Document Directory文件夹,以便存储至AWS
能否确保这些函数等待内部异步任务完成?(部分异步任务在forEach循环中执行,并非单个任务)
进一步,能否让两个copyFilesToDocumentDirectory()并发执行,且在执行zipDocumentDirectory()前等待它们完成?
原代码
import React, { Component } from 'react'; import { zip } from 'react-native-zip-archive'; import RNFS from 'react-native-fs'; export default class AddMedia extends React.Component { state = { photoAssets: [], videoAssets: [], videoThumbnails: [], thumbnailReady: false }; zipDocumentDirectory() { var path = RNFS.DocumentDirectoryPath; console.log("Zipped"); zip(path, path + "/urls.zip") .then((path) => { console.log("Zip complete"); }) .catch((err) => { console.log(err); }); }; deleteContentsOfDocumentDirectory() { var path = RNFS.DocumentDirectoryPath; var data = RNFS.readDir(path) .then((results) => { results.forEach(result => { /* I assume each item here is a FILE */ RNFS.unlink(result.path) .then(() => { console.log("File Deleted"); }) .catch((err) => { console.log(err.message); }); }); }); }; copyFilesToDocumentDirectory(assets) { var path = RNFS.DocumentDirectoryPath; assets.forEach(asset => { RNFS.exists(asset.uri) .then((status) => { if(status) { var newPath = path + "/" + asset.fileName;; console.log("Copying from: ", asset.uri, " -- to: ", newPath); RNFS.copyFile(asset.uri, newPath); }; }); }); }; storeToAWS() { this.deleteContentsOfDocumentDirectory(); this.copyFilesToDocumentDirectory(this.state.photoAssets); this.copyFilesToDocumentDirectory(this.state.videoAssets); this.zipDocumentDirectory(); }; // ... Render code etc; };
已做尝试
我编写了上述代码,认为可通过Promise解决该问题,但对Promise/async/await较为陌生。尝试为每个方法添加Promise以等待完成,但函数仍同步执行,异步任务滞后。输出显示zipDocumentDirectory()中的"Zipped"日志早于copyFilesToDocumentDirectory()内的异步命令。
修改后的代码
import React, { Component } from 'react'; import { zip } from 'react-native-zip-archive'; import RNFS from 'react-native-fs'; export default class AddMedia extends React.Component { state = { photoAssets: [], videoAssets: [], videoThumbnails: [], thumbnailReady: false }; zipDocumentDirectory() { var path = RNFS.DocumentDirectoryPath; console.log("Zipped"); new Promise((resolve, reject) => { zip(path, path + "/urls.zip") .then((path) => { console.log("Zip complete"); resolve(); }) .catch((err) => { console.log(err); reject(); }); }); }; deleteContentsOfDocumentDirectory() { var path = RNFS.DocumentDirectoryPath; new Promise((resolve, reject) => { var data = RNFS.readDir(path) .then((results) => { results.forEach(result => { /* I assume each item here is a FILE */ RNFS.unlink(result.path) .then(() => { console.log("File Deleted"); resolve(); }) .catch((err) => { console.log(err.message); reject(); }); }); }); }); }; copyFilesToDocumentDirectory(assets) { var path = RNFS.DocumentDirectoryPath; assets.forEach(asset => { new Promise((resolve, reject) => { RNFS.exists(asset.uri) .then((status) => { if(status) { var newPath = path + "/" + asset.fileName;; console.log("Copying from: ", asset.uri, " -- to: ", newPath); RNFS.copyFile(asset.uri, newPath); resolve(); }; }); }); }); }; storeToAWS = async () => { await this.deleteContentsOfDocumentDirectory(); await this.copyFilesToDocumentDirectory(this.state.photoAssets); await this.copyFilesToDocumentDirectory(this.state.videoAssets); // 2. Zip temporary folder storage (with encryption) await this.zipDocumentDirectory(); }; }
输出日志
LOG Zipped LOG Copying from: XYZ/FEB964FB-3ABB-4CF7-A3B0-1E90BD1932C4.jpg -- to: XYZ/FEB964FB-3ABB-4CF7-A3B0-1E90BD1932C4.jpg
解决方案
你的问题核心是没有让函数返回Promise,而且forEach循环里的异步任务没有正确等待全部完成。下面是修正后的完整代码,解决所有问题:
修正后的代码
import React, { Component } from 'react'; import { zip } from 'react-native-zip-archive'; import RNFS from 'react-native-fs'; export default class AddMedia extends React.Component { state = { photoAssets: [], videoAssets: [], videoThumbnails: [], thumbnailReady: false }; // 返回Promise,确保zip完成后才继续执行后续逻辑 zipDocumentDirectory = async () => { const path = RNFS.DocumentDirectoryPath; console.log("开始压缩"); try { const zipPath = await zip(path, path + "/urls.zip"); console.log("压缩完成:", zipPath); } catch (err) { console.log("压缩失败:", err); throw err; // 抛出错误让上层处理 } }; // 等待所有文件删除完成 deleteContentsOfDocumentDirectory = async () => { const path = RNFS.DocumentDirectoryPath; try { const results = await RNFS.readDir(path); // 用Promise.all等待所有删除任务完成 await Promise.all(results.map(result => { return RNFS.unlink(result.path) .then(() => console.log("文件已删除:", result.path)) .catch(err => { console.log("删除失败:", err.message); throw err; }); })); } catch (err) { console.log("读取目录失败:", err.message); throw err; } }; // 等待所有文件复制完成 copyFilesToDocumentDirectory = async (assets) => { const path = RNFS.DocumentDirectoryPath; // 用Promise.all等待所有复制任务完成 await Promise.all(assets.map(async asset => { try { const status = await RNFS.exists(asset.uri); if (status) { const newPath = path + "/" + asset.fileName; console.log("正在复制:", asset.uri, " -> ", newPath); await RNFS.copyFile(asset.uri, newPath); console.log("复制完成:", newPath); } } catch (err) { console.log("复制失败:", err.message); throw err; } })); }; storeToAWS = async () => { try { // 第一步:等待删除操作完成 await this.deleteContentsOfDocumentDirectory(); // 第二步:并行执行照片和视频的复制任务,等待全部完成 await Promise.all([ this.copyFilesToDocumentDirectory(this.state.photoAssets), this.copyFilesToDocumentDirectory(this.state.videoAssets) ]); // 第三步:等待压缩完成 await this.zipDocumentDirectory(); console.log("所有操作完成,可上传至AWS"); } catch (err) { console.log("流程执行出错:", err); // 这里可以添加错误处理逻辑,比如提示用户操作失败 } }; // ... Render code etc; };
关键修正点
- 所有异步函数返回Promise:使用
async/await语法,确保每个函数都能被await正确等待,之前的代码只是创建了Promise但没有返回,导致await无效。 - 处理循环中的异步任务:把
forEach换成map,配合Promise.all等待循环中所有异步任务完成,避免只等待第一个任务结束就继续执行。 - 并行执行复制任务:用
Promise.all包裹两个copyFilesToDocumentDirectory调用,让它们同时执行,提升效率,且确保两者都完成后再执行压缩。 - 错误处理:添加
try/catch捕获异常,并且在子函数中抛出错误,让上层统一处理,避免单个任务失败导致流程混乱。
这样修改后,执行顺序会严格按照:删除目录内容 → 并行复制照片和视频 → 压缩目录,所有异步任务都会等待完成后再进入下一步。
内容的提问来源于stack exchange,提问作者impression7vx
相关产品推荐
相关产品推荐

