无法从节点模块中的异步瀑布获取返回值

时间:2015-11-29 19:02:33

标签: javascript node.js asynchronous express promise

我有一个节点模块,它使用异步瀑布执行一些操作。它独立运行,并在通过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);
    }
}

我通过jQuery AJAX请求调用该路径,文件写得很好,但是,我没有看到返回的数据在控制台中打印出来,就像我期望的那样:

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);
}

并不感到惊讶它不起作用,只是一个想法。如何将返回的值恢复为调用模块的函数?或者我刚刚做了一些根本不正确的事情?

2 个答案:

答案 0 :(得分:4)

您不能将异步的内容视为同步内容。而是传递一个回调:

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);
}

答案 1 :(得分:0)

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

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;