【问题标题】:async waterfall not saving correctly with mongoose异步瀑布无法使用猫鼬正确保存
【发布时间】:2017-03-08 00:11:05
【问题描述】:

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

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

一旦完成,就会创建没有问题的测试,但它确实节省了第一个函数的时间。最初(在尝试异步之前)我将“新的 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);
});
} 

【问题讨论】:

  • 你总是立即调用callback,尽管已经启动了一个异步函数。您需要将回调传递给它,例如 .save(callback);!对于那个 for 循环,您需要嵌套一个 async.map
  • if (err) { callback(err); } 没有意义。该范围内没有callback

标签: javascript node.js mongoose async.js


【解决方案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);
});

【讨论】:

  • 你真的应该使用async.map 而不是async.each。这会让你得到finalQuestions 隐含的。
  • 这似乎让我走上了正确的道路,但是,我现在收到一条错误消息,指出“无效的 select() 参数。必须是字符串或对象。”查找后,我添加了 async.map 来代替 foreach。
  • 错误地allTestQuestions.findById 使用了两个回调函数。更新了答案。
  • @TalhaAwan 现在一切正常!感谢您的帮助,我将能够对此建模我未来的异步工作,以便我可以了解更多前进:)
【解决方案2】:

回调在异步函数(save 和 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');
    });
}

【讨论】:

    猜你喜欢
    • 2014-11-16
    • 2013-10-24
    • 2018-08-12
    • 2018-03-11
    • 2013-03-14
    • 2020-08-01
    • 2016-02-09
    • 2013-10-23
    • 2019-01-22
    相关资源
    最近更新 更多