API 设计——分页

两种分页方案

页大小 + 页号起始位置 + 条数

浏览方式

  • 初始翻页
  • 指定位置(收藏、输入)
  • 无限滚动加载
  • 改变每页列表项

请求方式

  • 元数据,HEAD/archive,响应头,X-TAG-NAME,调用一次前端本地存储
  • 条目列表, GET/archive
  • 频繁更新的数据,元数据与列表数据合一;抑或添加定时任务以 HEAD 模式请求

分页 API 设计

如果要取得资源列表,往往会遇到一个问题:分页,这时候的 API 该如何设计呢?以 RESTful API 为例来分析。

先打开 https://api.github.com/?,找到 repository_search_url "https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}"

这里第一个问题是 URI 的设计,我们分页时,分页信息其实是查询参数,不应该成为 URI 的一部分。因此,我们得到 repositories? 分页参数。

接下来,我们来看分页参数怎么设计。我们有两种方案:一种是“页大小 + 页号”,一种是“起始位置 + 条数”。

哪种更好呢?推荐使用后者,因为页码在本质上是前端的概念,前端可以按照每次 100 项向后端请求数据,但是展示给用户的时候用 10 项每页展示。如果我们在 API 中规定了页号,那么使用起来容易导致困惑。甚至,前端也可能完全不分页,而是使用“无限滚动”瀑布流式加载数据,这种模式下要映射出一个页码的概念,也会很别扭,而“起始位置 + 条数”的模式则适应性更强,在两种概念下都很容易理解。同时,在数据库中的分页也是完全相同的模式,可以直接把它们传给数据库去查询。

命名方面,在一个组织内要尽量统一。如果有以前的 API,要避开重命名参数;条数避免命名为 length,因为它和数据长度、字符长度同名,容易干扰其它代码和第三方库。

返回值,状态码要遵循规范,列表中没有数据时状态码为 200,并返回空数组。而有数据时,要返回一个和符合条件的数据列表。

可以在响应头中增加自定义头,如上述 Github API 中自定义响应头 Link 记录分页导航信息,以及其它一些 X-Github-××× 自定义属性。

对于没有缓存机制的请求,可以定义一个 X-Record-Count,用它来表明符合条件的总条数,前端可以保存,意味着没必要每次请求都重新求一次元数据,可以减少服务器的压力,这样把请求拆分成两个:一个用来获取条目列表(GET/repositories),一个用来获取相关的元数据(HEAD/repositories),相关的元数据只需在初始化时调用一次即可,不用每次都触发。当然,这种方式可能导致新增的数据不能在换页时立刻刷新出来。如果确实需要频繁刷新总数,可以选择使用最初的元数据、数据列表合一的 API,也可以写一个逻辑定时 HEAD 请求来刷新数据。

API 的设计取决于需求,没有一劳永逸的解决方案,适合业务需求的 API 才是友好的 API。


本文节选/参考 《AngularJS深度剖析与最佳实践》,案例部分我替换成了 Github 的 API,能直接访问,可以查看线上业务效果。

发布了110 篇原创文章 · 获赞 53 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/xianghongai/article/details/86063485