在开发小程序时,我们经常需要从数据源获取所有数据。然而,微搭的限制是每次只能最多获取 200 条记录,这对我们的业务需求并不符合。
为了解决这个问题,我们可以实现分页机制,以便获取全部数据。以下是具体的实现思路和代码示例。
代码实现
const allImportData = []; // 用于存储所有导入数据
const pageSize = 200; // 每页最多200条记录
let pageNumber = 1; // 当前页码
// 首先获取初始数据,以确定总记录数
const initialResponse = await context.callModel({
name: 'dcdr', // 数据源标识
methodName: 'wedaGetRecordsV2', // 方法标识
params: {
orderBy: [{ createdAt: "desc" }], // 按创建时间倒序排序
select: { $master: true }, // 返回主表字段
getCount: true, // 请求总记录数
pageSize: pageSize, // 每页记录条数
pageNumber: pageNumber, // 当前页码
compatibleWithV1: true // 兼容性设置
}
});
// 将第一页的数据存入数组中
allImportData.push(...initialResponse.records);
// 获取总记录数和总页数
const totalRecords = initialResponse.total;
const totalPages = Math.ceil(totalRecords / pageSize); // 向上取整,确保页码正确
// 定义一个数组,用于存储后续页的请求
const fetchPromises = [];
// 异步请求后续页的数据
for (let i = 2; i <= totalPages; i++) {
fetchPromises.push(
context.callModel({
name: 'dcdr',
methodName: 'wedaGetRecordsV2',
params: {
orderBy: [{ createdAt: "desc" }],
select: { $master: true },
getCount: false, // 不需要再次获取总数
pageSize: pageSize,
pageNumber: i,
compatibleWithV1: true
}
}).then(response => response.records) // 处理响应数据
);
}
// 使用 Promise.all 并行执行所有请求,并收集返回的数据
const pagesData = await Promise.all(fetchPromises);
pagesData.forEach(pageRecords => allImportData.push(...pageRecords)); // 将后续页的数据添加到总数组中
代码解析
我们拆解一下思路,首先我们定义了每页的显示条数和页码
1. 定义参数
const pageSize = 200;
let pageNumber = 1;
这里我们总是每次取200条符合他的API的要求,然后页面从第一页开始获取
因为最终返回的数据是一个数组,所以我们定义一个变量用来存储从数据源读取到的数据
const allImportData = [];
2. 获取初始数据
接着我们就先调用获取多条的方法,查询一下第一页的数据
const initialResponse = await context.callModel({
name: 'dcdr',
methodName: 'wedaGetRecordsV2',
params: {
orderBy: [{ createdAt: "desc" }],
select: { $master: true },
getCount: true,
pageSize: pageSize,
pageNumber: pageNumber,
compatibleWithV1: true
}
});
这里name就是我们数据源的标识,methodName是我们的方法标识。
params是我们方法调用的入参,这里orderBy是排序字段,select是返回的字段,$master:true表示返回全部字段。
getCount表示返回总记录条数,在返回的结果里是通过total属性体现。
pageSize是每页的返回数据条数,pageNumber表示第几页,compatibleWithV1: true这个表示要返回关联关系主表的字段,如果你的表的字段设置了关联关系这个才起作用
allImportData.push(...initialResponse.records);
这一行的代码的意思是把我们查询到的第一页的数据存入数组中,数组如果需要存入数据的可以调用push方法存入
括号里边我们用了展开的语法,这样就会把第一页的数据全部展开存入,这种类似于我们自己实现用循环的语法
for (let record of initialResponse.records) {
allImportData.push(record);
}
3. 计算总记录和总页数
接着我们返回记录总条数,并且记录总页数
const totalRecords = initialResponse.total;
// Calculate total pages based on pageSize and totalRecords
const totalPages = Math.ceil(totalRecords / pageSize);
这里我们用了Math.ceil方法,这个表示向上取整,比如我们计算是5.2页,那么上取整就变成了6页。因为到了最后一页有可能会少于200条,这样处理保证我们的页码是正确的
4. 并行请求后续页的数据
接着我们定义了一个数组用来异步加载后续的数据
const fetchPromises = [];
如果你直接用await的语法等待每页返回,云函数就会超时报错,我们使用异步执行,这样可以节约时间
for (let i = 2; i <= totalPages; i++) {
fetchPromises.push(
context.callModel({
name: 'dcdr',
methodName: 'wedaGetRecordsV2',
params: {
orderBy: [{ createdAt: "desc" }],
select: { $master: true },
getCount: false,
pageSize: pageSize,
pageNumber: i,
compatibleWithV1: true
}
}).then(response => response.records)
);
}
// Await and collect all pages' records
const pagesData = await Promise.all(fetchPromises);
最后这一部分就是去组装我的查询,每次循环都放入数组中,用Promise.all去并行的执行
5. 收集所有数据
在所有请求完成后,通过 forEach 将返回的数据合并到 allImportData 中
pagesData.forEach(pageRecords => allImportData.push(...pageRecords));
forEach 是一个数组的方法,用于遍历数组中的每个元素。
在每次循环时,都会调用小括号内的箭头函数。箭头函数是一种简洁的函数写法,左侧是传入的参数(在这里是 pageRecords),右侧是具体的执行逻辑。
在这个例子中,我们提取出当前元素(一个数组),并使用展开语法(…)将它的所有元素添加到最终结果数组 allImportData 中。
总结
通过以上方法,我们成功地实现了对数据源的全部数据进行分页获取。这种做法不仅提高了数据请求的效率,还确保了我们可以灵活地处理大量数据。希望这个技术分享能对您在使用微搭开发小程序时有所帮助!