最近做个独立项目,需要从一个第三方平台的 API 获取订单数据,但是该平台的 API 只能返回类似下面格式的数据
{
data: {
count: 100000,
items: [
{
_id: "575d74b6427b9e8f40d5b619",
num_iid: 1,
name: "0",
__v: 0
},
{
_id: "575d74b6427b9e8f40d5b61a",
num_iid: 2,
name: "1",
__v: 0
}]
}
}
上面这个数据是我测试生成的,其中 num_iid 是该平台唯一的,可以关联到商品记录,现在我需要把这个数据同步到我的系统上进行处理,那么这里面有这几个问题:
1. 第三方平台的数据可能随时更新,比如订单的状态
2. 该平台并不提供更新订阅的接口,所以订单是否更新了,我的系统并不知道
3. 该平台除了这个接口,还有一个根据订单 id 获取订单详情的接口
我的系统需要满足:
1. 数据需要和该平台同步
2. 数据的同步可以有半天的延时
3. 目前可以选择最简单的处理,在系统运行过程中去选择优化的办法
NodeJS, MongoDB
初步是选择了递归来处理,从平台分页获取数据,数据数据后根据平台的 count 来判断后面是否还要数据,如果有,再进行请求,如果没有了,对数据进行处理后返回;这个方案我没有处理好,JS 异步特性没有利用起来,读者朋友可以试下。
最后,选定的方案是:
1. 先给平台发一个请求,获得 **count**
2. 根据 **count** 和我的 **pageSize** 来判定需要多少个请求
3. 组装所有的请求,合并成一个 Array
4. 使用 Promise.all(Array) 来进行处理
5. 最后对结果数据进行下处理,然后同步到数据库
将获取订单的请求进行封装
``` const Request = require('request');
/**
* api request
* @param pageNo 页码
* @param pageSize 每页数据量
*/
const promiseReq = function(pageNo, pageSize) {
const url = http://127.0.0.1:3001/users/list?pageNo=${pageNo}&pageSize=${pageSize}
;
console.log(start request, pageNo: ${pageNo}, pageSize: ${pageSize}
);
return new Promise((resolve, reject) => {
Request(url, (error, response, body) => {
if (!error && response.statusCode === 200) {
resolve(JSON.parse(body));
} else {
reject(error);
}
})
})
}
```
先发一个小请求,得到订单总量
const pre = yield promiseReq(1, 5);
const count = pre.data.count;
判定需要多少个请求
const pageSize = 100;
const length = Math.ceil(count / 100);
合并请求
const reqs = [];
for (let i = 0; i < 10; i++) {
reqs.push(promiseReq(i+1, pageSize));
}
请求
const ret = yield Promise.all(reqs);
得到了数据后,进行相应的处理即可
对于数据入库,有 2 个办法:
1. 因为数据是全部拉取回来的,那么本地的纪录可以全部抹去,数据重新入库
2. 通过 **mongoose** 的 **findOneAndUpdate** 来处理,对存在的数据进行更新,不存在的数据进行入库
这个办法利用了 Promise.all() 来处理,因为每个请求都是异步的,所以处理起来速度很快。
但同样也存在一些问题,因为第三方平台的 API 使用会有次数限制,以及每次都大量获取数据,如果订单量比较小没有问题,但如果订单量特别多,这个办法就有很大的优化空间了。
对于后续在运行中可以进行优化,如对于未收货等订单,可以单获取这个订单的状态然后进行更新;根据本地的数据记录,和平台的总量之间计算出增量部分,然后合理处理 pageNo 等
最后,有其他解决办法的朋友,在评论里提出
关注我的微信公众号和微博,第一时间收到文章推送和交流
微信公众号
微博
欢迎在分答上直接向我提问