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

如何让函数等待jszip.loadAsync()执行并返回正确结果?

问题分析:async/await未生效导致Backup函数提前返回Pending Promise

问题描述

我是JavaScript及async/await的新手,尝试编写一个Backup函数读取zip压缩包,返回非空文件数、总文件数和文件总大小。但函数返回pending promise,且在Backup函数内的console.log输出前就打印了该promise,await未按预期生效。使用Node.js v18.12.1。

原Backup函数代码

const jszip = require('jszip')
const fs = require('fs')
async function Backup(path) {
    let files = 0
    let notEmpties = 0
    let size = 0
    fs.readFile(path, async (err, data) => {
        if (err) console.log(err)
        await jszip.loadAsync(data).then((zip) => {
            zip.forEach(async (path, file) => {
                files++
                await file.async('arraybuffer').then((data) => {
                    if (data.byteLength > 0) {
                        console.log(file.name, data.byteLength)
                        notEmpties++
                        size += data.byteLength
                    }
                })
            })
        })
    })
    return [notEmpties, files, size]
}

原执行代码

async function start(){
    return await Backup('C:\\Users\\Szymon\\Desktop\\(DOKUMENTY)20221027fbs083114601.zip')
}
//start
try {
    console.log(start());
} catch (error) {
    console.log(error);
}

核心问题点

  • 异步回调导致函数提前返回:Backup函数中使用了fs.readFile的回调写法,这个回调是异步执行的,但Backup函数会直接跳过回调逻辑,提前执行return语句,此时统计变量还是初始值0,且返回的Promise会提前resolve,而实际的zip解析逻辑还在后台运行。
  • zip.forEach不支持异步等待:zip.forEach不会等待传入的async回调执行完成,会一次性遍历所有zip条目,导致后续的await file.async(...)无法同步统计数据,异步流程完全失控。
  • async/await与.then()混用导致逻辑混乱:代码中同时使用await和.then()嵌套,破坏了async/await的线性异步流程,更容易出现时序问题。
  • 执行代码未正确处理Promise:console.log(start());直接打印了start函数返回的Promise对象,而不是等待Promise resolve后获取结果,所以会看到pending状态的Promise。

修正后的代码

改造后的Backup函数

使用Promise版本的文件读取API,并用Promise.all等待所有文件处理完成:

const jszip = require('jszip')
const fs = require('fs').promises; // 使用Promise化的fs模块

async function Backup(path) {
    let files = 0
    let notEmpties = 0
    let size = 0
    try {
        // 用await读取文件,替代回调写法
        const data = await fs.readFile(path);
        // 等待zip包加载完成
        const zip = await jszip.loadAsync(data);
        
        // 收集所有文件的异步处理任务
        const fileTasks = [];
        zip.forEach((_, file) => {
            files++;
            // 将每个文件的处理逻辑包装为异步函数,加入任务数组
            fileTasks.push(async () => {
                const fileData = await file.async('arraybuffer');
                if (fileData.byteLength > 0) {
                    console.log(file.name, fileData.byteLength);
                    notEmpties++;
                    size += fileData.byteLength;
                }
            });
        });
        
        // 等待所有文件处理任务完成
        await Promise.all(fileTasks.map(task => task()));
        
        return [notEmpties, files, size];
    } catch (err) {
        console.error('处理zip包时出错:', err);
        throw err; // 抛出错误让调用者捕获处理
    }
}

修正后的执行代码

正确等待Promise resolve后输出结果:

async function start(){
    try {
        const result = await Backup('C:\\Users\\Szymon\\Desktop\\(DOKUMENTY)20221027fbs083114601.zip');
        console.log('统计结果:', result);
        return result;
    } catch (error) {
        console.error('启动备份任务出错:', error);
    }
}

// 执行异步函数
start();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 12:35:24