英文:
javascript - sync data from IndexedDB and onsuccess update status
问题
I'm using Vanilla javascript for now.
The problem is - I have a IndexedDB where I keep events (let's call them punches). The logic is whenever user punches something, a new record is created in IndexedDB. The record looks like this:
{punchedon: 1687522698067, controlpointid: '1', method: '3', qrcodetext: '4', latitude: '5', ... synchronized: 0}
I have a dedicated field "sychronized" (1/0) in my IndexedDB record, that for each punch carries information whether this particular punch was already synced with server or not.
I have a procedure that is triggered whenever the browser comes back online, that should loop through all records that haven't been synced yet (synchronized=0), send them to the server and IF (AND ONLY IF) the server responds OK, to set synchronized=1.
However I'm struggling with how both IndexedDB and HTTPRequests are asynchronous.
This is the pseudocode I have so far, but I realize it does not work properly (it will update synchronize=1 even if the call to server fails).
function syncPunch(punch) {
httpRequest = new XMLHttpRequest();
if (!httpRequest) {
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open("GET", "https://server/punch.php?controlid=123&teamid=123×tamp=ABC...."); // fake call
httpRequest.send();
}
function syncUnsynced() { // sync all not yet synced punches
let tx = db.transaction(['punches'], 'readwrite');
let store = tx.objectStore('punches');
let syncIndex = store.index('synchronized'); // I have an index on the synchronized field, I query only those synchronized=0
let keyRng = IDBKeyRange.only(0);
const cursorRequest = syncIndex.openCursor(keyRng);
cursorRequest.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const punch = cursor.value;
const punchKey = cursor.value.key;
synchPunch(punch); // here I need to wait (react on / callback / promise??) to make sure the call was succesfull
console.log("Now fake-syncying " + JSON.stringify(punch));
punch.synchronized = 1;
const updateRequest = cursor.update(punch); // if this update fails and the call was sucesfull, I can live with that. But in normal scenario, I don't want to sync something that has been synced already.
console.log("Updated " + punchKey);
cursor.continue();
}
}
}
I tried to understand the Promises from the doc, but boy I got lost.
Any help on how to implement this logic appreciated.
英文:
I'm using Vanilla javascript for now.
The problem is - I have a IndexedDB where I keep events (let's call them punches). The logic is whenever user punches something, a new record is created in IndexedDB. The record looks like this:
{punchedon: 1687522698067, controlpointid: '1', method: '3', qrcodetext: '4', latitude: '5', ... synchronized: 0}
I have a dedicated field "sychronized" (1/0) in my IndexedDB record, that for each punch carries information whether this particular punch was already synced with server or not.
I have a procedure that is triggered whenever the browser comes back online, that should loop through all records that haven't been synced yet (synchronized=0), send them to the server and IF (AND ONLY IF) the server responds OK, to set synchronized=1.
However I'm struggling with how both IndexedDB and HTTPRequests are asynchronous.
This is the pseudocode I have so far, but I realize it does not work properly (it will update synchronize=1 even if the call to server fails).
function syncPunch(punch) {
httpRequest = new XMLHttpRequest();
if (!httpRequest) {
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open("GET", "https://server/punch.php?controlid=123&teamid=123&timestamp=ABC...."); // fake call
httpRequest.send();
}
function syncUnsynced() { // sync all not yet synced punches
let tx = db.transaction(['punches'], 'readwrite');
let store = tx.objectStore('punches');
let syncIndex = store.index('synchronized'); // I have an index on the synchronized field, I query only those synchronized=0
let keyRng = IDBKeyRange.only(0);
const cursorRequest = syncIndex.openCursor(keyRng);
cursorRequest.onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
const punch = cursor.value;
const punchKey = cursor.value.key;
synchPunch(punch); // here I need to wait (react on / callback / promise??) to make sure the call was succesfull
console.log("Now fake-syncying " + JSON.stringify(punch));
punch.synchronized = 1;
const updateRequest = cursor.update(punch); // if this update fails and the call was sucesfull, I can live with that. But in normal scenario, I don't want to sync something that has been synced already.
console.log("Updated " + punchKey);
cursor.continue();
}
}
}
I tried to understand the Promises from the doc, but boy I got lost.
Any help on how to implement this logic appreciated.
答案1
得分: 1
你可以使用Promises和async/await语法,如下所示,它包括Promise并确保仅在服务器调用成功时进行同步:
function syncPunch(punch) {
return new Promise((resolve, reject) => {
const httpRequest = new XMLHttpRequest();
if (!httpRequest) {
reject(new Error("XMLHttpRequest not supported"));
}
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
resolve();
} else {
reject(new Error("Server request failed"));
}
}
};
httpRequest.open(
"GET",
"https://server/punch.php?controlid=123&teamid=123×tamp=ABC...."
); // fake call
httpRequest.send();
});
}
async function syncUnsynced() {
const tx = db.transaction(["punches"], "readwrite");
const store = tx.objectStore("punches");
const syncIndex = store.index("synchronized");
const keyRng = IDBKeyRange.only(0);
const cursorRequest = syncIndex.openCursor(keyRng);
cursorRequest.onsuccess = async (e) => {
const cursor = e.target.result;
if (cursor) {
const punch = cursor.value;
const punchKey = cursor.key;
try {
await syncPunch(punch); // 等待服务器调用完成
console.log("Now fake-syncing " + JSON.stringify(punch));
punch.synchronized = 1;
const updateRequest = cursor.update(punch);
console.log("Updated " + punchKey);
} catch (error) {
console.error("Failed to sync punch:", error);
}
cursor.continue();
}
};
}
英文:
you can use Promises and async/await syntax, as follow incorporates promise and ensures that the synchronization only happens if the server call is successful:
function syncPunch(punch) {
return new Promise((resolve, reject) => {
const httpRequest = new XMLHttpRequest();
if (!httpRequest) {
reject(new Error("XMLHttpRequest not supported"));
}
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
resolve();
} else {
reject(new Error("Server request failed"));
}
}
};
httpRequest.open(
"GET",
"https://server/punch.php?controlid=123&teamid=123&timestamp=ABC...."
); // fake call
httpRequest.send();
});
}
async function syncUnsynced() {
const tx = db.transaction(["punches"], "readwrite");
const store = tx.objectStore("punches");
const syncIndex = store.index("synchronized");
const keyRng = IDBKeyRange.only(0);
const cursorRequest = syncIndex.openCursor(keyRng);
cursorRequest.onsuccess = async (e) => {
const cursor = e.target.result;
if (cursor) {
const punch = cursor.value;
const punchKey = cursor.key;
try {
await syncPunch(punch); // Wait for the server call to complete
console.log("Now fake-syncing " + JSON.stringify(punch));
punch.synchronized = 1;
const updateRequest = cursor.update(punch);
console.log("Updated " + punchKey);
} catch (error) {
console.error("Failed to sync punch:", error);
}
cursor.continue();
}
};
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论