定时同步订单信息
有这么一个场景👇
由于网络的问题,我们创建订单并付费成功了。但是,在调用同步订单接口的时候,出现了网络的问题等不可抗拒的因素而同步不成功。这个时候,就会造成订单的状态不正确,那么,我们有什么措施解决或者减少这种情况的?
嗯~
我们可以采用下面的方案:
- 使用浏览器存储,将订单信息存储在
IndexedDB
- 将信息存储在电脑本地
使用 IndexedDB
在之前的文章中,我们已经提及 前端使用 IndexedDB 存储。
这里,我们采取第二种方法 - 将信息存储在电脑磁盘。下面是我们的思路👇
这里我们使用的开发环境 👇
版本:Windows 10 专业版
版本号:22H2
电脑上拆分了多个磁盘
C
,D
,E
,F
- 在同步订单的接口执行前,先将订单机器信息记录到本地
- 在应用的首页,每隔 * 分钟轮询本地的记录,同步到远程服务
- 如果同步成功,则删除本地的信息记录;同步失败的订单下次轮询
👌。思路有了,我们来实现下,这里假设你已经安装了对应的 Node
环境。
写入文件
我们将订单信息记录在 D
盘下:
export const LOCAL_DISK_ORDER_INFO_PATH = "d:\\app-name\order-info"; // 订单信息存放的路径
export interface DiskSaveOrderInfo {
billNo: string;
billPayTime: string;
payWay: string
// ... other properties
}
我们将执行下面的操作进行保存。
// 获取订单的文件路径
export const getOrderFilePath = (orderId: string) => {
return path.join(LOCAL_DISK_ORDER_INFO_PATH, `${orderId}.json`); // 存储为 json 文件
};
// 保存订单到文件
export const saveOrderToFile = async (orderId: string, order: DiskSaveOrderInfo) => {
const filePath = getOrderFilePath(orderId);
// 创建文件路径
if (!fs.existsSync(LOCAL_DISK_ORDER_INFO_PATH)) {
try {
// 创建对应的文件夹
await fs.promises.mkdir(LOCAL_DISK_ORDER_INFO_PATH, { recursive: true });
} catch (error) {
console.error("fs.promises.mkdir", "创建目录失败", error);
}
} else {
fs.writeFileSync(filePath, JSON.stringify(order, null, 2)); // 写入数据
}
};
读取文件
我们从磁盘中读取保存的订单信息👇
// 从文件中读取订单 - 读取单个文件
export const readOrderFromFile = (orderId: string): DiskSaveOrderInfo | null => {
const filePath = getOrderFilePath(orderId);
try {
const data = fs.readFileSync(filePath, "utf8");
return JSON.parse(data);
} catch (error) {
console.error("fs.readFileSync", `readOrderFromFile - 读取订单 ${orderId} 失败`, error);
return null;
}
}
// 读取指定文件夹下的所有订单信息
export const getAllOrderFiles = (): DiskSaveOrderInfo[] => {
try {
const orderFiles = fs.readdirSync(LOCAL_DISK_ORDER_INFO_PATH);
const orderFilesData = orderFiles
.filter((file) => file.endsWith(".json"))
.map((file) => {
// 获取订单号
const orderId: string = file.replace(/\.json$/, "");
const data: DiskSaveOrderInfo | null = readOrderFromFile(orderId);
return data;
});
const result = orderFilesData.filter((data) => data !== null);
return [...result] as DiskSaveOrderInfo[];
} catch (error) {
console.error("getAllOrderFiles", "获取所有订单文件失败", error);
return [];
}
}
删除文件
我们删除磁盘上保存的订单,如下👇
// 删除订单文件
export const deleteOrderFile = (orderId: string): boolean => {
const filePath = getOrderFilePath(orderId);
try {
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
return true;
}
return false;
} catch (error) {
console.error("fs.unlinkSync", `删除订单 ${orderId} 文件失败`, error);
return false;
}
};
执行保存
在同步订单接口之前,我们将相关的信息记录下
export function usePayDone() {
const billNo = useStore(SelectorBillNo);
const notifyPaySuccessFn = async (payWay: PayWayEnum) => {
try {
// 保存订单信息到本地
await saveOrderToFile(billNo, {
billNo,
billPayTime: `${new Date().getTime()}`,
payWay
})
} catch (error) {
console.error("saveOrderToFile()", `保存订单 ${billNo} 信息到本地失败`, error);
}
// 执行同步订单到远程的代码 ...
}
return {
notifyPaySuccessFn
}
}
同步到远程
我们将本地的订单信息读取出来,然后依次向远程发起请求同步👇
// 定时同步本地订单的信息 - 这里可以自行实现是间隔多久触发下面的代码
export const useSyncOrders = () => {
const handleSyncOrderFn = async () => {
// 获取本地磁盘所有的订单信息
const orderFiles = getAllOrderFiles();
if (orderFiles.length === 0) {
return Promise.resolve();
}
const syncPromises = orderFiles.map((file) => {
return new Promise(async (resolve, reject) => {
try {
// 同步订单信息接口
await postNotifyPaySuccess({
billNo: file.billNo,
payWay: file.payWay,
});
// 如果同步成功,则删除订单
deleteOrderFile(file.billNo);
resolve(true);
} catch (error){
console.error("deleteOrderFile()", `删除本地订单 ${file.billNo} 失败`, error);
reject(error);
}
});
});
return Promise.all(sysnPromises);
}
return {
hanleSyncOrderFn,
};
}
至此,我们已经完成了订单信息的存储,订单的读取和订单的同步。
拜拜,Happy Coding!