2016-06-22 2 views
0

IndexedDB을 광범위하게 사용하는 앱을 개발하고 있습니다. 내가하려는 것은 종업원 테이블과 회사 테이블의 데이터를 저장하는 것입니다.

각 직원은 회사에 속하며 직원 개체에는 Company's ID이 있고 엔티티 둘 다의 개체는 다음과 같습니다.콜백에서 IDBTransaction을 반환하면 TransactionInactiveError가 throw됩니다.

회사의 목적 :

{"id":1,"name":"ABC"} 

직원의 목적은 :

{"id":100,"name":"E1","company_id":1} 

나는 자동 증가 키를 사용하여 회사의 정보를 저장하고있어 너무 내 최종 목적, (그것을 appid이라고 함) 회사의 모습은 다음과 같습니다.

{"id":1,"name":"ABC","appid":1} 

회사의 레코드를 하나씩 삽입 할 때 appid가 자동으로 증가합니다. 내가의 localid을 얻을 수있어

{"id":100,"name":"E1","company_id":1,"company_app_id":1} 

: 직원의 객체를 삽입하는 동안
지금 내가 좋아하는 직원의 객체가 보이게하기 위해 회사의 localid (appid)을 찾아 직원의 객체에 저장하려면 같은 직원의 세부 사항을 저장하는 동안 방법을 호출하여 기업 : 나는 테이블에서 직원의 데이터를 삽입 할 때 위의 코드와

var transaction = db.transaction(['employees'], 'readwrite'); 
var objStore = transaction.objectStore('employees'); 
var company_id=employeeobject.company_id; 
companyDB.getCompanyById(company_id,function(companyObject){ 
     transaction = db.transaction(['employees'], 'readwrite'); 
     objStore = transaction.objectStore('employees'); 
     // If I comment above two lines it throws me exception. 
     var request=objStore.put(employeeobject); 
     request.onsuccess = function (e) { 
      // using it for next insertion. 
     }; 
}); 

문제는 콜백 함수에서 trascation을 다시해야 할 때마다 경우 때문에 돈 열리지 마라. 트랜잭션이 다시 throw됩니다 TransactionInactiveError.

나는 SO의 특정 오류를 검색했으며 현재 범위에서 더 이상 사용되지 않는 즉시 트랜잭션이 비활성화됨을 발견했습니다.

위의 코드는 직원의 몇 가지 오브젝트가있을 때 완벽하게 작동합니다. 그러나 ~ 1K의 데이터로 동일한 코드를 실행하려고하면 (정상 실행 시간 x ~ 10)이 걸립니다.

정상적인 실행 시간이란 회사의 로컬 ID를 가져 오지 않고 직원의 세부 정보를 직접 저장하지 않고 의미합니다.


그래서 제 질문은, 내가 적어도 실행 시간와 회사의 localid을 포함하여 직원의 데이터를 삽입 할 수있는 가장 좋은 방법은 무엇입니까? 아니면 내가 뭔가 잘못하고있는거야?

답변

0

흠, 어쩌면 이렇게 도움이 될까요?

function addCompany(db, company, callback) { 
    var tx = db.transaction('companies', 'readwrite'); 
    var store = tx.objectStore('companies'); 
    var request = store.add(company); 
    request.onsuccess = callback; 
} 

function addEmployee(db, employee, callback) { 
    var tx = db.transaction('employees', 'readwrite'); 
    var store = tx.objectStore('employees'); 
    var request = store.add(employee); 
    request.onsuccess = callback; 
} 


function addCompanyThenEmployee(db, company, employee, callback) { 
    addCompany(db, company, onAddCompany); 

    function onAddCompany(event) { 
    var newAppId = event.target.result; 
    employee.company_app_id = newAppId; 
    addEmployee(db, employee, callback); 
    } 
} 


var company = {'id': 1, 'name': 'xyz'}; 
var employee = {'id': 1, 'name': 'xyz'}; 

var request = indexedDB.open(...); 
request.onsuccess = function(event) { 
    var db = event.target.result; 
    addCompanyThenEmployee(db, company, employee, onAddCompanyThenEmployee.bind(null, company, employee)); 
}; 

function onAddCompanyThenEmployee(company, employee, event) { 
    console.log('Added company', company, 'and employee', employee); 
}; 
+0

이것은 하나의 회사와 단일 직원을 위해 해결됩니다 (내가 여기에 실제 데이터/논리를 엉망으로하고있어, 이것은 단지 설명하는 것입니다). 필자가 작성한 코드는 단일 항목으로 완벽하게 작동합니다. 나는 1K 이상의 컴피티와 10K의 직원을 보유하고 있습니다. 그래서이 경우 어떻게 작동하는지 알아낼 수 없습니다! –

1

companyDB.getCompanyById()을 어떻게 구현하는지에 따라 다릅니다.

제시된 바와 같이 비동기식 블랙 박스입니다 (네트워크 요청을하고있는 것일 수도 있습니다). 그리고 여러분이 발견 한 것처럼 인덱싱 된 DB 트랜잭션은 생성 직후에만 활성화되고 (1) 생성 된 직후에만 활성화됩니다. (2) 그 트랜잭션은 "제어가 이벤트 루프로 돌아갈 때까지". 자세한 내용이 없으면 최선의 방법은 작업을 배치하는 것입니다. N 직원에 대한 getCompanyById() 조회를 수행 한 다음 해당 N 레코드를 작성합니다.

그러나 맨 위에있는 설명에서 ... ... 직원 테이블과 회사 테이블의 데이터 ... 이것은 어쩌면 모든 단일 트랜잭션을 사용하는 단일 인덱싱 된 DB 데이터베이스 내에있을 수 있습니다.

var tx = db.transaction(['companies', 'employees'], 'readwrite'); 
employee_records.forEach(function(record) { 
    var company_id = record.company_id; 
    var req = tx.objectStore('companies').get(company_id); 
    req.onsuccess = function() { 
    var company = req.result; 
    record.company_app_id = company.app_id; 
    tx.objectStore('employees').put(record); 
    }; 
}); 

+0

아니요, 동일한 indexeddB 데이터베이스가 아닙니다. 먼저 모든 회사를 데이터베이스에 삽입 한 다음 직원의 세부 정보를 회사의 localid에 삽입하려고합니다. 위의 코드/로직에는 네트워크 호출이 전혀 없습니다. –

관련 문제