我有一个获得问题行的请求
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);
}
});
}
});
});
}
答案 0 :(得分:1)
原因是,i
循环中的for
值在每次迭代时都会更改,而函数answer.getAllByQuestionId
是异步的,并且当每次迭代调用回调时i
answer.getAllByQuestionId
1}}值基本上不同于边界。而且,函数rows.forEach
的回调应该只有两个参数而不是三个参数。
最简单的解决方法是,您可以使用for
代替async
循环来处理此问题,如下所示。否则,您可以使用承诺模块,例如bluebird
,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;
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));