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

async waterfall not saving correctly with mongoose

这是我第一次使用异步,虽然我已经在网上搜索并尝试了系列和瀑布方法,但我的结果是一样的。我想我已经非常接近让这项工作正常进行了,但就是不能让它 100% 工作。

我正在尝试根据从前面发送的时间和测试问题参数创建测试 end.The 主要问题是底部创建测试的最终方法发生在搜索中间方法之前对于问题,样本答案(如果有的话),然后将其放入一个对象数组中。

完成后,正在创建没有问题的测试,但它确实节省了第一个函数的时间。最初(在尝试异步之前)我将 "new interviewtest" 方法包装在 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);
});
} 

在中间函数中,您有一个调用数据库的 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);
});

回调在异步函数(保存和 findById)之外,像这样执行 stg :

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