2012-10-16 5 views
8

나는 비교적 단순한 질문을 가졌다 고 생각하지만 나는 서클에서 계속 생각하고있다. 심지어 구글도 나에게 내가 할 수있는 대답을주지 않는다.Javascript for 루프 내에서 WebSQL 쿼리. 완료 시점을 아는 방법?

기본적으로 WebSQL을 사용하여 로컬에 저장된 일부 레코드를 복사하려고합니다. 복사가 문제는 아니지만 프로그램을 진행하기 전에 모든 복사 작업이 완료된 시점을 알아야합니다.

WebSQL 호출이 비동기 적으로 처리되므로 일반적으로 이러한 작업을 수행하는 유일한 방법은 콜백 함수를 사용하는 것입니다. 그러나 쿼리는 for 루프 내에서 수행되기 때문에 콜백 함수는 코드에 표시된 것처럼 완료된 첫 번째 쿼리에서 실행되므로 사용할 수 없습니다. 다음과 같이

코드는 다음과 같습니다 나는 또한 콜백 함수 i == results.rows.length를 호출하려고했지만, 그 모든 쿼리가 완료되는 날 슈어하지 않습니다

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); 
       }) 
      } 
     }); 
    }); 
} 

.

여러분 중 일부는 이전에 같은 문제가 발생했습니다. 따라서이 문제를 해결하고 for 루프가 완료되었을 때만 콜백 함수가 호출되도록하는 방법에 대한 도움을 받으십시오.

미리 감사드립니다.

+0

인서트를주기가 완전히 트랜잭션 내에서 이동 있도록이 결과를 통해주기에서 내부 transacion 이동이 가능합니까? – Stan

답변

8

일반적인 접근 방식은 각 개인 기록 대신 for 루프를 처리하기 위해 재귀 비동기 콜백을 사용하는 것입니다.

레코드가 더 남아있는 동안 비동기 콜백 자체가 호출됩니다. 레코드가 남아 있지 않으면 제공된 콜백을 호출 할 수 있습니다.

당신의 내면의 콜백 핸들러의 내용을 대체 할 아래 코드 :

(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

답변 해 주셔서 감사합니다. 나는 재귀 함수를 사용하는 것을 결코 생각하지 못했다! – user1749815

+0

아이디어를 주셔서 감사하지만 그것은 배열이 아니므로 Web-SQL 결과가 shift() 함수를 지원하지 않는 것 같습니다. 카운터를 수동으로 증가 시켜야만했습니다. – Matthieu

2

"콜백"기능의 실행 횟수를 유지하고 결과 집합의 전체 양에 도달하면 진행하는 것이 가장 좋습니다.

가 여기에 수정을 코드입니다 : 나를 위해로서

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. 
         }); 
        }); 
       } 
      } 
     }); 
    }); 
} 

, 나는 비트 combersome을 할 WebSQL의 비동기 API를 발견하고 WebSQL 데이터베이스는 표준이되었습니다 (멀리 갈 가능성이 있기 때문에 떨어졌다), 나는 모두가 SequelSphere로 넘어서 전환 할 것을 권할 것이다. 모든 브라우저와 모든 플랫폼에서 작동하는 HTML5/JavaScript 관계형 데이터베이스입니다. 또한 localStorage에 데이터를 저장하여 모든 번거 로움없이 WebSQL의 모든 이점을 제공합니다.

위의 해결 방법이 도움이되지 않으면 알려주세요.

행운을 빈다.

존은 ... 이것에 대한

+0

당신은 정말로 SequelSphere에 관심을 표명해야합니다. – Alnitak

+0

좋은 포인트. 당신은 절대적으로 옳습니다. 죄송합니다 ... SequelSphere와 연결되어있어 플러그를 제공하는 데 도움이되지 않습니다. –

+0

p.s. 비동기 콜백은 번거롭지 않습니다.이 작업을 수행하는 방법에 대한 내 대답을 참조하십시오 _right! _ – Alnitak

관련 문제