无限滚动|使用JavaScript生成器在API上分页

191 阅读2分钟

无限滚动|使用JavaScript生成器在API上分页

使用JavaScript生成器编写干净的代码

在编写前端代码时,你可能会遇到这样的情况:你必须使用分页法从API中获取所有记录。你可以将代码分解成多个函数来完成。然而,维护这么多的变量,并将状态从一个函数传递到另一个函数,并不像它看起来那么简单。数据源的异步性使得它更加复杂。然而,你可以使用async-generator函数来简化它。在这篇文章中,我将解释你如何将这个复杂的逻辑分解成简化的函数。

1.创建一个模拟的数据湖/源

为了测试这些功能,你需要一个数据源。为了模仿真实的api数据源,我将创建一个假的用户列表。

const users = Array(1000)  .fill()  .map((_, i) => ({ name: `user${i}`, id: `id_${i}` }));const TOTAL_RECORDS = users.length;

2.获取用户的API函数

你可以使用一个基于承诺的API函数来获取记录。然而,我将使用async-await函数来创建这个Fetch user API函数

//service.js

上面的函数fetchUsers ,需要像pagelimit 的选项。Page被定义为分页的当前页,limit被定义为要获取的记录的限制。延迟只是和1000ms的虚拟延迟,以模仿实际的网络。

3.使用生成器函数获取所有记录

传统上,你可以使用递归写一个函数来解决这个问题。然而,写递归的版本过于复杂,难以理解。你也可以使用for-loop/while-loop使用async-await。请看下面的例子。

async function main() {  let records = [];  let options = { page: 0, limit: 100, end: 100, total_records: Infinity };

输出

正如你所看到的,使用while-loop函数,你的主函数不得不过多地担心其他变量,如记录分页选项。在这种情况下,生成器就会大放异彩。让我们试着把上面的例子转换为生成器。

/** * * @param {page, limit} start page index, limit/chunk of the records to fecth on each call * @default {0, 100} * @returns */async function* fetchAllRecords({ page = 0, limit = 100 } = {}) {  while (true) {    const records = await fetchUsers({ page: page++, limit });    yield records;    if (records.done) return;  }}

输出

正如你所看到的,使用生成器使代码看起来更简单,更容易阅读。

注意:如果你注意到这一行for await (let record of api) ,在这一行中,我们看到的是生成器的异步循环。这个await 信号for-loopapi 对象是异步迭代器函数来迭代。

Codesandbox。

结论

异步等待并不能使你的API运行得更快。它只是简化了代码,增加了代码的可读性。正如某个聪明人曾经说过的。