异步瀑布不能正确保存猫鼬

async waterfall not saving correctly with mongoose

本文关键字:确保 保存 不能 布不能 异步      更新时间:2023-09-26

这是我第一次使用异步,虽然我已经在网上搜索并尝试了系列和瀑布方法,但我的结果是相同的。我想我很接近有这个工作正确,但只是不能得到它的工作100%。

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

完成后,将创建没有问题的测试,但它确实节省了第一个函数的时间。最初(在尝试异步之前),我在2sec setTimeout中包装了"new interviewtest"方法,这工作得很好,但我知道有一个更好,更有效的方法来做到这一点。

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循环,它调用数据库,你在循环外调用callback。它应该包装在另一个async函数中。试试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),这样做:

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