如果用户在系统/浏览器崩溃时重新打开浏览器,请检查并更新 localStorage

Lax*_*Sam 5 javascript typescript

我正在尝试根据每个选项卡localStorage的值sessionStorage和对象更新存储的列表的值。window我这里有不同的场景:

  1. 用户在每个选项卡中启动一个新进程。
  2. 刷新/关闭选项卡
  3. 浏览器已关闭
  4. 系统崩溃 - 此处未单击浏览器关闭按钮。这是直接关闭

我写的代码如下。此代码更新上述前两种情况的所有存储中的值。但在第三种和第四种情况下它不会更新。我可以做出哪些改变来使这项工作正常进行?

const data = useRef('');

const setDatatInLocalStorage = (event?) => {
  if (!event) {
    event = window.event;
  }
  if (event.key == 'dataList') {
    const localStorageDataList = JSON.parse(event.newValue || '[]');
    localStorage.setItem('dataList', JSON.stringify(localStorageDataList));
  }
};

window.addEventListener('storage', setDatatInLocalStorage, {
  once: true,
});

window.onbeforeunload = function () {
  const sessionStorageDataList = JSON.parse(
    sessionStorage.getItem('dataList') || '[]',
  );
  if (sessionStorageDataList.length > 0) {
    let localStorageDataList = JSON.parse(
      localStorage.getItem('dataList') || '[]',
    );
    if (localStorageDataList.length > 0) {
      localStorageDataList = localStorageDataList.filter(
        (data) => !sessionStorageDataList.includes(data),
      );
      localStorage.setItem('dataList', JSON.stringify(localStorageDataList));
    }
  }
  sessionStorage.removeItem('dataList');
};

window.onload = function () {
  const sessionStorageDataList = JSON.parse(
    sessionStorage.getItem('dataList') || '[]',
  );
  if (sessionStorageDataList.length > 0) {
    let localStorageDataList = JSON.parse(
      localStorage.getItem('dataList') || '[]',
    );
    if (localStorageDataList.length > 0) {
      localStorageDataList = localStorageDataList.filter(
        (data) => !sessionStorageDataList.includes(data),
      );
      localStorage.setItem('dataList', JSON.stringify(localStorageDataList));
    }
  }
  sessionStorage.removeItem('dataList');
};

const updatedataList = (data) => {
  if ((window as any).dataList) {
    (window as any).dataList.push(data);
  } else {
    (window as any).dataList = [data];
  }
  sessionStorage.setItem(
    'dataList',
    JSON.stringify((window as any).dataList),
  );
  if (
    'dataList' in localStorage &&
    !isEmpty(localStorage.getItem('dataList'))
  ) {
    const localStorageDataList = JSON.parse(
      localStorage.getItem('dataList') || '[]',
    );
    localStorageDataList.push(data);
    localStorage.setItem('dataList', JSON.stringify(localStorageDataList));
  } else {
    localStorage.setItem('dataList', JSON.stringify([data]));
  }
};

const removedataList = () => {
  if ((window as any).dataList) {
    (window as any).dataList.shift();
  }
  sessionStorage.setItem(
    'dataList',
    JSON.stringify((window as any).dataList),
  );
  if ('dataList' in localStorage) {
    let localStorageDataList = JSON.parse(
      localStorage.getItem('dataList') || '[]',
    );
    localStorageDataList = localStorageDataList.filter(
      (item) => item !== data.current,
    );
    localStorage.setItem('dataList', JSON.stringify(localStorageDataList));
  }
};


const callData = () => {
  if (!data.current) {
    data.current = uuid();
  }

  updatedataList(data.current);
  const intervalID = setInterval(() => {
    const localStorageDataList = JSON.parse(
      localStorage.getItem('dataList') || '[]',
    );
    if (localStorageDataList.indexOf(data.current) === 0) {
      clearInterval(intervalID);
      //logic to execute
      removedataList()
    }
  }, 10000);
};
Run Code Online (Sandbox Code Playgroud)

这里我需要更新dataList所有存储中的。它是一个用作队列的数组。我在浏览器关闭时清空了所有 sessionStorages 和 localStorage (无论是用户单击还是由于系统崩溃)。我怎样才能做到这一点?如果我的方法不适用于所有用例,也欢迎任何其他实现建议。

Lax*_*Sam 1

在网上搜索时,我想到了一个想法,即取最新时间戳和上次更新时间戳之间的时间差。基于以下是示例代码:

let intervalId: { current: NodeJS.Timeout | null } =
    useRef(null);

// Start a setInterval that updates the timestamp every second
const updateTimeStampForCurrentIdInLocalStorage = (id) => {
    intervalId.current = setInterval(() => {
      const timestampsObj = getTimerObjectFromLocalStorage();
      const currentTime = new Date();
      timestampsObj[id] = currentTime.getTime();
      localStorage.setItem(
        'timestampsObj',
        JSON.stringify(timestampsObj),
      );
    }, 1000);
  };

const mainFunction = () => {
  const mainProcessIntervalId = setInterval(() => {
    // timestampobj from localstorage.
    const timestampsObj = JSON.parse(
      localStorageRef.current.getItem('timestampsObj') || '{}',
    );
    if (someCondition) {
      clearInterval(mainProcessIntervalId);
      //continue
    } else {
      const idsInTimer = Object.keys(timestampsObj).filter(
        (id) => id !== currentId,
      );
      idsInTimer.forEach((id) => {
        const currentTime = new Date();
        const lastUpdated = new Date(timestampsObj[id]);
        const timeDiff =
          (currentTime.getTime() - lastUpdated.getTime()) / 1000;
        if (timeDiff > thresholdTime) {
          const timestampsObj = getUuidTimerObjectFromLocalStorage();
          if ((timestampsObj.length > 0)) {
            delete timestampsObj[id];
            localStorage.setItem('timestampsObj', JSON.stringify(timestampsObj));
          }
          if (intervalId.current) {
            clearInterval(intervalId.current || 0);
          }
        }
      });
    }
  }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

要在刷新时删除数据,应在事件上调用一个函数onBeforeUnload。主要逻辑是检查timeDiff现有 id 的当前时间和上次更新时间之间的时间,如果它们超过阈值,则将其删除。