今天,我们来谈论一个场景👇
在网络不是很好的情况下,我们如果没有做离线缓存的话。我们应该如何同步应用的信息到后端服务呢?
嗯🤔
第一步
我们可以采用轮询的方式,在达到轮询的上限之后,停止网络请求。
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 中的相关记录;如果请求依旧失败,保留相关的记录,在下次网络好的时候执行请求发送。
特殊情况处理
按照正常来说,我们进行 第一步 -> 第二步 -> 第三步 -> 第一步 循环♻️操作,我们必定能够将信息同步到后端服务。
当时,遇到一些问题,我们还是要特殊对待,下面是笔者想到的一些场景👇
-
比如,我们的软件版本升级中,会不会将存储
IndexedDB的相关信息清空掉,这就影响了数据的完整性。 -
比如,如果用户对内容的需求比较紧急,那么,我们是否将可以相关的内容(eg: 用户生成的图片,视频)存储在本地磁盘,然后我们通过远程的软件去手动拿文件之类的信息,再让后端直接操作
sql进行存储,当然,这个跟业务形态有关。 -
比如,我们是否可以对大文件,比如几兆的图片做缓存,在下次进来的时候,我们不需要重新从互联网上下载下来,而是通过
memory获取文件。
etc...