如何将行传递给内部多个请求

时间:2016-11-27 00:15:14

标签: javascript node.js

我有一个获得问题行的请求

con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows)

然后我需要得到每个问题的答案。

for(var i=0; i < rows.length; i++){     
            answer.getAllByQuestionId(rows[i].id, function(err, data){

我毫无困难地得到答案和问题。但是我无法在rows[i] is undefined

之后将答案添加到每个问题中

以下是整个方法:

this.getAllByQuizId = function(quizId, callback) {
    connection.acquire(function(err, con) {
      con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) {
        if (err) callback(err); 
        completed_requests = 0;

        for(var i=0; i < rows.length; i++){     
            answer.getAllByQuestionId(rows[i].id, function(err, data, rows){

                    rows[i].answers = data;
                    completed_requests++;

                    if (completed_requests == rows.length - 1) {
                        callback(null, rows);
                    }
                });
            }                               
        });    
    });
}

3 个答案:

答案 0 :(得分:1)

原因是,i循环中的for值在每次迭代时都会更改,而函数answer.getAllByQuestionId是异步的,并且当每次迭代调用回调时i answer.getAllByQuestionId 1}}值基本上不同于边界。而且,函数rows.forEach的回调应该只有两个参数而不是三个参数。

最简单的解决方法是,您可以使用for代替async循环来处理此问题,如下所示。否则,您可以使用承诺模块,例如bluebirdthis.getAllByQuizId = function(quizId, callback) { connection.acquire(function(err, con) { con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) { if (err) callback(err); completed_requests = 0; rows.forEach(function(row){ answer.getAllByQuestionId(row.id, function(err, data){ row.answers = data; completed_requests++; if (completed_requests == rows.length - 1) { callback(null, rows); } }); }); }); }); } 等。

my_list

答案 1 :(得分:1)

这里有一些问题:

  • 如果err回调中设置query(),则您不会提前返回。这将导致其余的回调在错误时继续执行,因此将if (err) callback(err)更改为if (err) return callback(err)

  • rows[i]将不会是您在getAllByQuestionId()回调中的预期,因为回调执行时i的值已经等于rows.length而不是调用getAllByQuestionId()时行的索引。有几种解决方案,包括:

    • 使用const / let存储当前行,因为const / let变量的范围限定为最接近的任何类型的块(而{{{ 1}}变量的范围限定为最近的功能块):

      var
    • 使用for (var i = 0; i < rows.length; ++i) { const row = rows[i]; answer.getAllByQuestionId(row.id, function(err, data, rows) { row.answers = data; if (++completed_requests === rows.length) callback(null, rows); }); } 创建一个正确绑定当前值的新函数范围:

      rows.forEach()
  • 另一个问题是,您有两个名称相同的变量(rows.forEach(function(row) { answer.getAllByQuestionId(row.id, function(err, data, rows) { // ... }); }); ),并且您不清楚要将哪个变量传递给rows。我的猜测是来自callback()的{​​{1}},因为您在其元素上设置了rows属性。无论哪种方式,您都需要更改其中一个或两个的名称,以免造成问题。

  • 最后,您没有处理可能传递给query()回调的错误。

答案 2 :(得分:1)

两件事。

如果您有自定义SQL查询并且想要获得答案,则应该使用连接。

select * from questions q inner join answers a 
on q.questionId = a.questionId where `quizId` = ?

但是要使用更新的JavaScript语法干净地使用多个查询来编写代码,您可以使用以下内容:

import promiseAllEnd from 'promiseallend';

dropErrors = async (promises) => promiseAllEnd(promises).filter(x => x!=undefined);

getQuestions = async id => await conPoolQuery('select .. from questions' //

getAnswers = async id => await conPoolQuery('select .. from answers'//

getQuiz = async(id) => await dropErrors(await getQuestions(id).map(getAnswers));