可以't从节点模块中的异步瀑布中获取返回值

Can't get return value from async waterfall in node module

本文关键字:异步 布中 返回值 获取 模块 节点 可以      更新时间:2023-09-26

我制作了一个节点模块,它使用异步瀑布执行一些操作。它独立工作,并在通过AJAX调用运行时完成所有任务,然而,我的AJAX回调从未得到它的返回值。

//node module 
var boilerplateFn = function(params){
    async.waterfall([
        function(callback){
            //do task 1
            callback(null, results);
        },
        function(results, callback){
            //task 2 is write
            fs.writeFile(path, results, function(err){
                if (err){
                    console.log(err);
                }else{
                    callback(null, results)
                }
            })
        }
    ], function(err, results){
        return results
    });
}
module.exports = exports = boilerplateFn;

这样可以正确地写入文件,如果我在最后一个函数中执行console.log,我可以看到我的结果字符串。

然而,当我试图将其包含在这样的路线中时:

var components = require('./app/js/node_components');
app.get('/process/:scale/:type', function(req, res){
    var data = processRequest(req.params);
    res.json(data);
});
function processRequest(params){
    console.log(componentents.boilerplateFn(params)) //prints undefined in Terminal
    return {
        result: componentents.boilerplateFn(params);
    }
}

然后我通过jQueryAJAX请求调用路由,文件写得很好,但是,我没有看到返回的数据像我预期的那样打印在控制台中:

return $.ajax({
        type: 'get',
        url: 'http://localhost:8888/' + paramStr,
        dataType: 'json'
    }).done(function(data){
        console.log('returned data', data) //returned data Object{}
    }).fail(function(jqObj, textStatus, err){
        console.log(jqObj, textStatus, err);
    })
});

我认为这意味着我的文件正在写入,但我的函数已经返回,所以它永远不会得到返回的文本。然而,我尝试在回调中包装res.json,但它没有改变任何内容。

    processRequest(req.params, function(data){
      res.json(data);
    });

function processRequest(params, callback){
    var data = componentents.boilerplateFn(params);
    callback(data);
}

这并不奇怪,它没有起作用,只是一个想法。如何将返回的值返回到调用模块的函数?或者我只是做了一些根本不正确的事情?

不能将异步的东西视为同步的。相反,传入一个回调:

var boilerplateFn = function(params, cb) {
  async.waterfall([
    function(callback) {
      // do task 1
      callback(null, results);
    },
    function(results, callback) {
      // task 2 is write
      fs.writeFile(path, results, function(err) {
        if (err) {
          callback(err);
        } else {
          callback(null, results);
        }
      })
    }
  ], cb);
}
module.exports = boilerplateFn;

然后像这样使用:

var components = require('./app/js/node_components');
app.get('/process/:scale/:type', function(req, res) {
  processRequest(req.params, function(err, data) {
    // TODO: check `err` first
    res.json({ result: data });
  });
});
function processRequest(params, cb) {
  components.boilerplateFn(params, cb);
}

您在这里又做了同样的事情:

function processRequest(params, callback){
    var data = componentents.boilerplateFn(params); //this writes undefined to data 
    callback(data);
}

最简单的解决方案是直接在.get请求中调用函数,不要过度设计

var components = require('./app/js/node_components');
app.get('/process/:scale/:type', function(req, res){
    componentents.boilerplateFn(req.params, function(err, results){
        if (err){
           //handle error
        }else{
            res.json(data);
        }
    });
});

var boilerplateFn = function(params, cb){
async.waterfall([
    function(callback){
        //do task 1
        callback(null, results);
    },
    function(results, callback){
        //task 2 is write
        fs.writeFile(path, results, function(err){
            if (err){
                console.log(err);
            }else{
                callback(null, results)
            }
        })
    }
], cb);
}
module.exports = exports = boilerplateFn;