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

React Native中如何在同步函数内顺序执行异步任务?

问题描述

我需要按特定顺序执行一系列包含异步任务的函数,要求这些函数必须顺序执行。代码需完成以下操作:

  1. 删除Document Directory中的当前内容(文件为持久化存储,但仅作临时使用)
  2. 将当前文件资源从原位置复制到Document Directory
  3. 压缩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;
};

关键修正点

  1. 所有异步函数返回Promise:使用async/await语法,确保每个函数都能被await正确等待,之前的代码只是创建了Promise但没有返回,导致await无效。
  2. 处理循环中的异步任务:把forEach换成map,配合Promise.all等待循环中所有异步任务完成,避免只等待第一个任务结束就继续执行。
  3. 并行执行复制任务:用Promise.all包裹两个copyFilesToDocumentDirectory调用,让它们同时执行,提升效率,且确保两者都完成后再执行压缩。
  4. 错误处理:添加try/catch捕获异常,并且在子函数中抛出错误,让上层统一处理,避免单个任务失败导致流程混乱。

这样修改后,执行顺序会严格按照:删除目录内容 → 并行复制照片和视频 → 压缩目录,所有异步任务都会等待完成后再进入下一步。


内容的提问来源于stack exchange,提问作者impression7vx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:05:29