2012-11-13 51 views
0

我试图显示Phonegap(科尔多瓦)应用程序中的项目列表,其中每个项目需要额外的查询。两个查询,其中第二个依赖于第一个

为了简单起见,我会用一个例子来解释它。假设一个student可以有多个course和一个course可以有许多student(多对多),我想显示一个列表显示学生注册到哪些课程。就像这样:

  • Student1:course1,course2
  • STUDENT2:course1,course3,当然5
  • 学生三:course2
  • ...

首先,我需要一个查询遍历所有学生,然后为每个学生查询数据库以了解学生注册的课程:

db.transaction(function(tx) { 
    tx.executeSql('SELECT `student`.`id`, `student`.`name` ' + 
      'FROM `student`', 
      [], 
      function(tx, resultSet) { 
       for(var i = 0; i < resultSet.rows.length; i++) { 
        tx.executeSql('SELECT `course`.`name` ' + 
          'FROM `student_has_course` ' + 
          'INNER JOIN `student` ON `student_has_course`.`student_id` = `student`.`id` ' + 
          'INNER JOIN `course` ON `student_has_course`.`course_id` = `course`.`id` ' + 
          'WHERE `student`.`id` = ?' 
          [resultSet.rows.item(i).id], 
          function(tx2, resultSet2) { 
           // TODO 
          }); 
       } 
      }); 
}, function(err) { 
    showError('Error getting students from the DB (' + err.message + ')'); 
}, function() { 
    alert('success!'); 
}); 

现在,问题是在第二个回调函数中(“TODO”是),我没有引用任何前一个查询的数据。例如,如果我尝试alert(i)它会提醒76,这相当于resultSet.rows.length。这显然是因为两个回调函数都是异步的。我怎么能克服这个问题并按照上面所示打印列表?

任何帮助极大的赞赏。

回答

2

您应该能够通过附加属性回调函数本身来解决这个问题如下:

cb = function cbfunc() { 
    doStuffWith(cbfunc.data) 
} 
cb.data = ... // whatever 
tx.executeSQL(..., cb) 

不过,我会三思而后行,如果我可以通过一个单一的生产预期的结果避免了二次回调查询。在这种情况下:

select student.id, student.name, course.name from student 
    inner join student_has_course on student.id = student_has_course.student_id 
    inner join course on student_has_course.course_id = course.id 
     order by student.id; 

,并在循环,比较与一个从以前的迭代知道何时打印新行和新的学生姓名,以获得您想要的输出格式的student.id。

+0

谢谢@jop。这只是一个解决方法,但我正在寻找一种通用的解决方案,在我看到的任何情况下都可以工作 – satoshi

+0

。我编辑它以提供更通用的解决方案,即使对于此特定示例,单个SQL仍然看起来更好。 – jop

+0

谢谢,解决方案工作:) – satoshi

相关问题