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

旧版Node.js无Promise时用async库实现串并行混合异步任务

问题根因

代码无法执行到任务3、4的核心原因是async库的执行规则:所有传入async流程的任务函数,必须在任务执行完成后主动调用入参提供的回调函数,通知async当前任务结束,流程才会向后推进。
你的代码中外层async.series的第一个任务块(负责执行任务1、2),在嵌套的串行流程跑完后,没有调用外层任务传入的回调,导致async始终判定第一个任务块未完成,永远不会进入下一个并行任务块。
另外你的readFile1函数错误分支调用回调后没有终止执行,会出现错误场景下重复调用回调的隐患,也需要修复。

修复后代码
const async = require('async');
const fs = require('fs');

const readFile1 = (name, callback) => {
        fs.readFile(name, 'utf-8', (err, data) => {
                if (err) {
                        // 错误回调触发后直接return,避免重复调用回调
                        return callback(err);
                }
                console.log(data);
                callback(null, data);
        });
}

async.series([
// 第一个任务块:串行执行任务1、任务2
function(taskBlockCb) {
        async.series([
                function(cb) {
                        readFile1('./1.txt', cb);
                },
                function(cb) {
                        readFile1('./2.txt', cb);
                },
        ], function(err, results) {
                console.log('series ', results);
                // 关键:当前任务块执行完毕,必须调用外层传入的块回调,通知async推进流程
                taskBlockCb(err, results);
        });
},
// 第二个任务块:并行执行任务3、任务4
function(taskBlockCb) {
        async.parallel([
                function(cb) {
                        readFile1('./3.txt', cb);
                },
                function(cb) {
                        readFile1('./4.txt', cb);
                },
        ], function(err, results) {
                console.log('parallel ', results);
                // 执行完调用块回调,标记当前任务块结束
                taskBlockCb(err, results);
        });
}
], function(err, allResults) {
        // 全流程最终回调
        if (err) {
                return console.error('流程执行异常:', err);
        }
        console.log('所有任务执行完成,结果:', allResults);
});
简化写法

这个串并行混合的流程不需要额外嵌套内层async.series,可以直接把串行任务平铺到外层series数组中,代码更简洁:

async.series([
    // 任务1
    cb => readFile1('./1.txt', cb),
    // 任务2
    cb => readFile1('./2.txt', cb),
    // 任务3、4并行块
    blockCb => {
        async.parallel([
            cb => readFile1('./3.txt', cb),
            cb => readFile1('./4.txt', cb)
        ], blockCb)
    }
], (err, res) => {
    if (err) return console.error(err);
    console.log('全部任务执行完成', res);
})
编写注意事项
  • 所有传给async的任务函数,无论执行成功还是失败,最终必须调用入参提供的回调,否则整个流程会永久卡住
  • 回调的第一个参数固定传错误对象,无错误时必须传null,第二个及之后的参数传任务的返回结果
  • 错误分支调用回调后记得加return终止后续逻辑,避免同个任务多次调用回调触发报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:09:25