2012-10-16 42 views
8

Tôi đoán tôi có một câu hỏi đơn giản tương đối, nhưng tôi cứ suy nghĩ trong các vòng kết nối và thậm chí Google không cho tôi câu trả lời mà tôi có thể làm việc cùng.Truy vấn Javascript WebSQL trong vòng lặp. Làm thế nào để biết khi nào kết thúc?

Về cơ bản tôi đang cố sao chép một số bản ghi được lưu trữ cục bộ bằng WebSQL. Sao chép không phải là vấn đề, nhưng tôi cần phải biết khi nào tất cả các hành động sao chép được hoàn tất trước khi chương trình của tôi có thể tiếp tục.

Cuộc gọi WebSQL được thực hiện không đồng bộ nên cách duy nhất để tôi thường làm những việc này là sử dụng chức năng gọi lại. Tuy nhiên, vì các truy vấn được thực hiện trong vòng lặp for, tôi không thể sử dụng hàm gọi lại vì nó sẽ kích hoạt tại truy vấn đầu tiên được hoàn thành như được hiển thị trong mã.

Mã này là như sau:

function copyRecords(old_parent_id, new_parent_id, callback){ 
    var db = openDatabase('test', '1.0', 'test', 50 * 1024 * 1024); 
    db.transaction(function (tx) { 
     tx.executeSql('SELECT * FROM table WHERE parent_id = ?', [old_parent_id], function(tx, results){ 
      for(var i = 0; i < results.rows.length; i++){ 
       db.transaction(function (tx2) { 
        tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)', [results.rows.item(i).name, new_parent_id], callback); 
       }) 
      } 
     }); 
    }); 
} 

Tôi cũng đã thử gọi hàm callback khi i == results.rows.length, nhưng điều đó không asure tôi rằng tất cả các truy vấn được hoàn thành.

Tôi đoán một số bạn đã gặp phải vấn đề tương tự trước đây, vì vậy bất kỳ trợ giúp nào về cách giải quyết điều này và đảm bảo rằng chức năng gọi lại chỉ được gọi khi vòng lặp hoàn thành được đánh giá cao.

Cảm ơn bạn trước.

+0

Có khả thi để di chuyển transacion trong ra khỏi chu kỳ thông qua các kết quả, do đó chu kỳ của BIG đi bên trong giao dịch hoàn toàn? – Stan

Trả lời

8

Cách tiếp cận thông thường cho việc này sẽ được sử dụng một async gọi lại đệ quy để xử lý mỗi bản ghi cá nhân thay vì một for vòng lặp.

Trong khi còn nhiều bản ghi, cuộc gọi lại không đồng bộ sẽ tự gọi. Khi không còn bản ghi nào, nó có thể gọi lại cuộc gọi lại được cung cấp của bạn.

Đoạn code dưới đây sẽ thay thế các nội dung của bộ xử lý gọi lại bên trong của bạn:

(function nextRecord() { 
    var row = results.rows.shift(); 
    if (row) { 
     db.transaction(function (tx2) { 
      tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)', 
       [row.item(i).name, new_parent_id], nextRecord); 
     }); 
    } else { 
     callback(); 
    } 
})(); 
+0

Cảm ơn bạn đã trả lời! Tôi không bao giờ nghĩ đến việc sử dụng các hàm đệ quy! – user1749815

+0

cảm ơn cho ý tưởng, nhưng có vẻ như kết quả web-sql không hỗ trợ chức năng shift(), vì nó không phải là một mảng. Vì vậy, tôi đã phải tăng một truy cập bằng tay, và nó đã làm việc! – Matthieu

2

Điều này được thực hiện tốt nhất bằng cách giữ số lượng thực thi hàm "gọi lại" và chỉ tiến hành khi nó đạt đến số lượng đầy đủ của tập kết quả.

Dưới đây là mã của bạn với những sửa đổi:

function copyRecords(old_parent_id, new_parent_id, callback){ 
    var db = openDatabase('test', '1.0', 'test', 50 * 1024 * 1024); 
    db.transaction(function (tx) { 
     tx.executeSql('SELECT * FROM table WHERE parent_id = ?', [old_parent_id], function(tx, results){ 
      if (results.rows.length == 0) 
       callback(); // don't forget this case! 
      else { 
       var nbrInserted = 0; // This will keep track of how many have been inserted 
       for(var i = 0; i < results.rows.length; i++){ 
        db.transaction(function (tx2) { 
         tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)', [results.rows.item(i).name, new_parent_id], function() { 
          ++nbrInserted; // increment this for every insert 
          if (nbrInserted == results.rows.length) // check if complete 
           callback(); // Do your callback. 
         }); 
        }); 
       } 
      } 
     }); 
    }); 
} 

Đối với tôi, tôi thấy các API async của WebSQL là một combersome bit, và kể từ khi cơ sở dữ liệu WebSQL có thể sẽ ra đi (tiêu chuẩn đã được bỏ qua), tôi khuyên mọi người nên chuyển sang SequelSphere. Đây là một cơ sở dữ liệu quan hệ HTML5/JavaScript hoạt động trên tất cả các trình duyệt và tất cả các nền tảng. Nó cũng lưu trữ dữ liệu trong localStorage, mang lại cho nó tất cả các lợi ích của WebSQL, mà không có tất cả các phức tạp.

Hãy cho tôi biết nếu giải pháp trên không hiệu quả với bạn.

Chúc may mắn!

john ...

+0

Bạn thực sự phải tuyên bố rằng mình quan tâm đến SequelSphere. – Alnitak

+0

Điểm tốt. Bạn hoàn toàn đúng. Xin hãy tha thứ ... Tôi đã kết nối với SequelSphere, và không thể giúp đưa phích cắm. –

+0

p.s. cuộc gọi lại không đồng bộ không cồng kềnh - hãy xem câu trả lời của tôi về cách thực hiện điều này _right! _ – Alnitak

Các vấn đề liên quan