进行回调等待,直到函数返回结果为节点js

时间:2018-04-25 18:49:11

标签: javascript node.js asynchronous callback

需要处理一系列文件。文件可以是不同类型的,因此有不同的功能进行处理。我期望遍历所有文件,在其中收集日志,最后返回一个存储所有日志的变量。

代码:

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)和回调(null)是异步的。 callback(null)首先完成,所有文件都被迭代,执行流程转到发送响应。同时功能仍在执行中。

如何解决这个问题:Haven没弄明白。理想情况下,回调会在返回null之前等待函数返回各自的值(并完成执行)。

无法做什么:使用计时器进行回调等待。正在处理的文件数量可以从1到数百,并且没有大小限制。处理每个文件可能需要的时间是未知的。

我尝试了什么:在函数执行完毕后返回回调。将函数的返回值赋给变量(例如test)并进行回调(测试)。两个人都没有工作。

2 个答案:

答案 0 :(得分:2)

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

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结合使用,以帮助解开此代码。我发现它们更容易使用,尤其是在复杂的流量控制情况下。

答案 1 :(得分:2)

你可以尝试类似的东西:

if(file_is_type1(file_from_list)){
   process_filetype_1(file_from_list, callback);
}

然后process_filetype_1看起来像:

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