滞后网络接口信息同步

189 阅读2分钟

今天,我们来谈论一个场景👇

在网络不是很好的情况下,我们如果没有做离线缓存的话。我们应该如何同步应用的信息到后端服务呢?

嗯🤔

第一步

我们可以采用轮询的方式,在达到轮询的上限之后,停止网络请求。

let up = 3;

const uploadFn = async () => {
  await handleFn(); // 处理上传
}

const entryFn = () => {
  try {
    await uploadFn();
  } catch(error) {
    up += 1;
    if (up <= 3) {
      entryFn(); // 发生错误时候,当请求的次数在允许的范围内,则接着尝试
    }
    console.error(error);
  }
}

第二步

如果使用轮询,尝试失败了。那么,这个时候,我们应该将相应的信息存储在本地。这个时候,我们应该选择用 IndexedDB 进行存储,而不是 LocalStorage 这类存储大小比较小的存储方案。

比如,我们同步一个订单失败了,这个时候,我们需要记录相关的订单的信息下来 👇

interface IPostBillMessageRequest {
  billId: string; // 账单 ID
  photoUrl: string; // 上传的图片链接地址,也可能是存放在机器本地的图片地址
  equipmentCode: string; // 设备编号
  // etc... 其他字段
}

interface IPostBillMessageResponse {
  status: string; // 订单的状态
}

export function syncBillMessage(body: IPostBillMessageRequest) {
  return http.post<IPostBillMessageResponse>({
    url: "path/to/sync/bill",
    body
  });
}

IndexedDB 上保存相关的信息👇

// 保存信息
const data = {
  id: "id_1", // billId
  value: JSON.stringify({name: "jimmy"})
}
addIndexedDBData(data);

具体参考上一篇文章 前端用 IndexedDB 存储

第三步

当网络恢复的时候,我们从存储空间 IndexedDB 中获取数据,然后采用第一步的方法,采用轮训的方式,向后端服务发送信息。

如果成功发送请求,那么,我们可以删除在 IndexedDB 中的相关记录;如果请求依旧失败,保留相关的记录,在下次网络好的时候执行请求发送。

特殊情况处理

按照正常来说,我们进行 第一步 -> 第二步 -> 第三步 -> 第一步 循环♻️操作,我们必定能够将信息同步到后端服务。

当时,遇到一些问题,我们还是要特殊对待,下面是笔者想到的一些场景👇

  1. 比如,我们的软件版本升级中,会不会将存储 IndexedDB 的相关信息清空掉,这就影响了数据的完整性。

  2. 比如,如果用户对内容的需求比较紧急,那么,我们是否将可以相关的内容(eg: 用户生成的图片,视频)存储在本地磁盘,然后我们通过远程的软件去手动拿文件之类的信息,再让后端直接操作 sql 进行存储,当然,这个跟业务形态有关。

  3. 比如,我们是否可以对大文件,比如几兆的图片做缓存,在下次进来的时候,我们不需要重新从互联网上下载下来,而是通过 memory 获取文件。

etc...

参考