首页 > 解决方案 > 使回调等到函数在节点js中返回结果

问题描述

有一组文件需要处理。文件可能有不同的类型,因此有不同的函数进行处理。我希望遍历所有文件,收集日志,最后返回一个存储所有日志的变量。

编码:

var file_list = req.body.filelist.split(','); //array of filenames
var logs = []; //logs about the file processing will be stored here

//iteration through each file
async.forEach(file_list , function(file_from_list , callback){
    if(file_is_type1(file_from_list)){
        process_filetype_1(file_from_list);
        callback(null);
    }
    else if(file_is_type1(file_from_list)){
        process_filetype_2(file_from_list);
        callback(null);
    }
    else{
        logs.push("Unknown file type");
    }
},function(error, result){
     return res.status(200).send({message: import_log});
});

有两种不同的函数,它们处理文件的逻辑不同。这是一个复杂的代码,但运行流畅,每个动作都在正确的时间执行。这是其中一个功能的抽象:

function process_filetype_1(file_from_list){
    async.auto({
        dosth_1: function(callback) {
            //logic implementation
        },
        dosth_2: ['dosth_1', function(callback) {
            //logic implementation
        }]
    }, function(error, results) {
        return results;
    });
}

会发生什么:所有文件都已处理,但迭代内的回调不等待函数完成执行。因此,在文件完成处理之前发送响应

为什么会发生:调用 process_filetype_1(file_from_list) 和 callback(null) 是异步的。callback(null) 首先完成,所有文件都被迭代,执行流程转到发送响应。与此同时,功能仍在执行中。

解决方法:还没想好。理想情况下,回调会在返回 null 之前等待函数返回它们各自的值(并完成执行)。

不能做什么:使用定时器让回调等待。正在处理的文件数量可以从 1 到数百,并且没有大小限制。处理每个文件可能花费的时间是未知的。

我已经尝试过:当函数完成执行时返回回调。将函数的返回值分配给变量(例如测试)并执行回调(测试)。没有一个工作。

标签: javascriptnode.jsasynchronouscallback

解决方案


如果你想使用回调风格的代码,那么任何调用回调的函数本身都必须采用回调函数:

function process_filetype_1(file_from_list, cb) {
    async.auto({
        dosth_1: function(callback) {
            //logic implementation
        },
        dosth_2: ['dosth_1', function(callback) {
            //logic implementation
        }]
    }, function(error, results) {
        cb(error, results);
    });
}

由于您的功能似乎没有做任何事情,您可以链接:

function process_filetype_1(file_from_list, cb) {
    async.auto({
        dosth_1: function(callback) {
            //logic implementation
        },
        dosth_2: ['dosth_1', function(callback) {
            //logic implementation
        }]
    }, cb);
}

另一种方法是使用 Promise 系统,可能与async/结合使用await以帮助解开此代码。我发现它们更容易使用,尤其是在复杂的流量控制情况下。


推荐阅读