使用mongoose无法正确保存异步瀑布

时间:2016-10-25 19:49:50

标签: javascript node.js mongoose async.js

这是我第一次使用异步,虽然我搜索了网络并尝试了系列和瀑布方法,但我的结果是一样的。我认为我非常接近正确地工作,但是不能让它100%工作。

我正在尝试根据从前端发送的时间和测试问题参数创建测试。主要问题是创建测试的底部的最终方法是在搜索问题的中间方法之前发生的,示例答案(如果有),然后将其放在对象数组中。

一旦完成,正在创建测试而没有任何问题,但它确实节省了第一个功能的时间。最初(在尝试异步之前)我包装了"新的面试测试"在2秒setTimeout中的方法,这工作正常,但我知道有一个更好,更有效的方法来做到这一点。

exports.create = function(req) {
console.log(req.body);
var testTime = 0;
var timer = req.body.timeValue;
var testQuestions = req.body.category;
var finalQuestions = [];

async.waterfall([
    function(callback) { **add total time into one value to be saved in the test**
        for (var i = 0; i < timer.length; i++) {
            if (timer[i] !== '') {
                testTime += parseInt(timer[i]);
            }
        }
        callback(null,testTime);
    },
    function(testTime,callback) { **find question and push it into array of objects**
        for (var i = 0; i < testQuestions.length; i++) {
            allTestQuestions.findById(testQuestions[i], function(err, result) {
                var test = {};
                test.text = result.text;
                test.answer = '';
                test.sample = result.sample;
                finalQuestions.push(test);
            });
        }   
        callback(null, testTime, finalQuestions);
    },
    function(testTime, finalQuestions, callback) { **create new test**
        new interviewTest({
            authCode: req.body.intAuthCode,
            name: req.body.intName,
            questions: finalQuestions, **questions**
            assignedDate: new Date,
            started: false,
            startedTime: '1970',
            completed: false,
            completedTime: '1970',
            time: testTime,
            timePerQuestion: []
        }).save(function(err, res) {
            console.log(err);
            if (!err) { console.log(res + " saved!"); } 
        });

        callback(null, 'done');
    }
], function (err, result) {
    if (err) { callback(err); }
    console.log(result);
});
} 

2 个答案:

答案 0 :(得分:1)

在中间函数中,你有一个调用数据库的for循环,你在循环外调用回调。它应该包含在另一个异步函数中。试试async.each或Bergi建议,async.map

async.waterfall([
    function(callback) {
        for (var i = 0; i < timer.length; i++) {
            if (timer[i] !== '') {
                testTime += parseInt(timer[i]);
            }
        }
        callback(null,testTime);
    },
   function(testTime,callback) {
    async.each(testQuestions, function(tQuestion, eachCallback){
        allTestQuestions.findById(tQuestion, function(err, result) {
            if(err){
                // you can either eachCallback(err) or just console.log it and keep going
            }
            var test = {};
            test.text = result.text;
            test.answer = '';
            test.sample = result.sample;
            finalQuestions.push(test);
            eachCallback()
        })
    }, function(err, result){
        callback(null, testTime, finalQuestions);
    })
},
    function(testTime, finalQuestions, callback) {
        new interviewTest({
            authCode: req.body.intAuthCode,
            name: req.body.intName,
            questions: finalQuestions,
            assignedDate: new Date,
            started: false,
            startedTime: '1970',
            completed: false,
            completedTime: '1970',
            time: testTime,
            timePerQuestion: []
        }).save(function(err, res) {
                console.log(err);
                if (!err) { console.log(res + " saved!"); }
                callback(null, 'done'); //call here
            });

      //  callback(null, 'done'); this should always be called inside the callback function
    }
], function (err, result) {
    if (err) { callback(err); }
    console.log(result);
});

答案 1 :(得分:0)

回调在异步函数(save和findById)之外,请执行以下操作:

function(testTime,callback) { **find question and push it into array of objects**
    for (var i = 0; i < testQuestions.length; i++) {
        allTestQuestions.findById(testQuestions[i], function(err, result) {
            ...
            finalQuestions.push(test);
            if(finalQuestions.length == testQuestions.length)
                return callback(null, testTime, finalQuestions);
        });
    }   

},
function(testTime, finalQuestions, callback) { **create new test**
    new interviewTest({
      ...
    }).save(function(err, res) {
        console.log(err);
        if (!err) { console.log(res + " saved!"); } 
        callback(null, 'done');
    });
}