同步数据来自IndexedDB,并在成功时更新状态。

huangapple go评论70阅读模式
英文:

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&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.

英文:

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&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); // 等待服务器调用完成

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

huangapple
  • 本文由 发表于 2023年6月26日 21:56:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76557358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定