记一次Promise在api接口合并中的妙用
栏目: JavaScript · 发布时间: 5年前
内容简介:关于接口合并(不知道有没有专门的术语,这里姑且如此描述),在这里解释一下,就是打开新页面第一次请求数据是一个api接口,滚动到底部加载更多数据时是另一个api接口上次作者在个人项目中遇到的post预检请求bug,水了一篇小文《关于接口合并,作者在项目开发文档中也有描述,有兴趣的可以去瞅瞅。
关于接口合并(不知道有没有专门的术语,这里姑且如此描述),在这里解释一下,就是打开新页面第一次请求数据是一个api接口,滚动到底部加载更多数据时是另一个api接口
一. 前言
上次作者在个人项目中遇到的post预检请求bug,水了一篇小文《 记一次跨域post请求数据之preflight request 》,这次再分享一下个人在api接口合并中如何妙用Promise,尽逮着这只羊使劲薅,毛都快秃了(逃;老规矩,本文只是记录在特定项目api中解决问题的思路,对读者朋友们或有启发那就最好不过了,关于接口合并到底好不好,有什么问题、错漏之处欢迎大家提出来分享,作者此文权当抛砖引玉。
关于接口合并,作者在项目开发文档中也有描述,有兴趣的可以去瞅瞅。
二. 背景介绍
脱离业务谈编码就是耍流氓。下面简单介绍一下猫眼的接口,就以猫眼首页api为例。
猫眼API接口分析
1 初始化获取当前热映电影列表
以下都将以 api_1 指称 初始化获取当前热映电影列表api接口
1.1说明
信息 | 说明 |
---|---|
功能 | 初始化获取电影信息 |
URL | //m.maoyan.com/ajax/movieOnInfoList |
格式 | JSON |
HTTP METHOD | GET |
1.2 请求参数
参数 | 类型 | 必选 | 说明 |
---|---|---|---|
token | String | false | 登录之后的凭证 |
1.3返回字段
字段 | 类型 | 说明 |
---|---|---|
movieList | Array | 电影列表(默认一次返回10条) |
total | Number | 列表总数目 |
movieIds | Array | 所有电影ID,总数同total,后续请求更多电影时必须依赖它们 |
coming | Array | 更多电影列表,第一次请求必定是空 |
1.4 接口示例
//m.maoyan.com/ajax/movieOnInfoList?token
{ "coming": [], "stid": "576591972453269000", "movieIds": [247295, 410629, 1206605, 248906, 341139, 1250341, 1218091, 344869, 1243239, 580298, 907653], "movieList": [ "同下方获取当前热映更多电影列表接口返回的coming字段" ], "stids": [ {"movieId": 247295, "stid": "576591972453269000_a247295_c0"} ], "total": 11 } 复制代码
2.1 获取当前热映更多电影列表
以下都将以 api_2指称 获取当前热映更多电影列表api接口
2.1 说明
信息 | 说明 |
---|---|
功能 | 获取hot更多电影列表 |
URL | //m.maoyan.com/ajax/moreComingList |
格式 | JSON |
HTTP METHOD | GET |
2.2 请求参数
参数 | 类型 | 必选 | 说明 | 列子 |
---|---|---|---|---|
token | String | false | 登录之后的凭证 | |
movieIds | String | true | 请求的电影ID,依赖初始化接口的接口返回字段movieIds | "1214652,1229799,1251606" |
2.3 返回字段
字段 | 类型 | 说明 |
---|---|---|
coming | Array | 更多电影列表 |
2.4 接口示例
//m.maoyan.com/ajax/moreComingList?token=&movieIds=1214652%2C1229799%2C1251606%2C1215114
{ "coming": [ { "id": 1214652, "comingTitle": "2月22日 周五", "globalReleased": true, "haspromotionTag": false, "img": "http://p0.meituan.net/w.h/movie/979266668d0e94dc83956a70d22b4eaa184105.jpg", "nm": "朝花夕誓-于离别之朝束起约定之花", "preShow": false, "rt": "2019-02-22", "sc": "9.2", "showInfo": "今天10家影院放映21场", "showst": "3", "star": "石见舞菜香,入野自由,茅野爱衣", "version": "", "wish": 76220, "wishst": 0, }, ...略 ] } 复制代码
上面两大坨数据,就是作者整理的api接口文档,仔细观察两个api接口的返回字段,都有一个coming字段,作者最初的灵感也是来自于它们,api_1接口的数据列表放在movieList字段中,我们下面就将以Promise处理coming和movieList来大做文章。
三. 方案
啰嗦到现在也没进入正题,可能有读者已经不耐烦了,作者也很急的,但是前戏要备足,大家稍等。
要进行接口合并,无非要解决两个问题,判断接口、处理数据
1 判断接口
api_2接口请求数据的时候必定需要知道请求的是那些电影的ID,那么我们肯定要在本地定义一个offset作为数据的偏移量,作者的项目是vue写的,就放在了vue的组件实例上了。我们将offset设为0,第一次请求时offset必定为0,我们就将offset的值作为判断接口的依据。
下面直接上代码
import { getInfoListAction } from '@/api' const { offset, limit, total } = this const isFirst = isFirst = offset === 0 const getMovieInfoList = getInfoListAction(isFirst) getMovieInfoList(params).then(data => { // ....数据处理此处略,详见下文 }) 复制代码
通过getInfoListAction 和 isFirst我们得到最终的api操作函数getMovieInfoList,关于getInfoListAction请看下面js代码
难道直接用if-esle来硬编码判断?作者当然不会这么糊弄大家了,请看下面
getInfoListAction是由getDataByAction(curry处理)接受两个api调用函数,返回一个接受Boolean参数判断返回哪个api接口函数的新函数,最终也就是上文使用了isFirst调用返回了最终的api函数getMovieInfoList。
// @addr src/api/index.js import request from '@/util/request' import { getDataByAction } from '@/util' const getMovieOnInfoList = request('/movieOnInfoList') const getMoreComingList = request('/moreComingList') export const getInfoListAction = getDataByAction(getMovieOnInfoList, getMoreComingList) // @addr src/util/index.js export const getDataByAction = (initAction, nextAction) => (isFirst) => isFirst ? initAction : nextAction // @addr src/util/request.js import Axios from 'axios' let baseURL = process.env.VUE_APP_URL const defaultConfig = { baseURL } const STATUS_CODE = 200 const instance = Axios.create(defaultConfig) const request = (url, method = 'get') => (params) => { return instance({ url, method, ...params }).then(resp => { if (resp.status === STATUS_CODE) { return resp.data } }) } export default request 复制代码
请忽略作者的request函数的丑陋封装,没有做错误处理,(逃
2 数据处理
由上文可知,我们最终的api调用函数调之后其实是返回了一个Promise{<resolve>:data}
我们在vue组件实例上定义了movieList存放数据,movieIds存放第一次返回时movieIds字段的数据,total数据总数。
// 接上文的省略的代码部分 // 暂时忽略params参数,下文有处理详解 /** * 1. 在promise.then的函数中,我们从data数据里取 movieIds, movieList, coming, total字段 * 2.1 我们以movieIds判断是第一次调用api接口(其他字段也可以,这里先偷懒),那么我们赋值需要* 的数据 movieIds,total,直接返回movieList数据. * 2.2 如果2.1没有执行,那么肯定是加载更多数据的接口api_2,我们直接返回coming字段 * 3. 从2.2、2.3我们获得了最后的数据Array,判断数据的长度,更新offset偏移量和movieList数据 * ps: setImgSize是处理图片的函数,不必理会 **/ getMovieInfoList(params).then(data => { const { movieIds, movieList, coming, total } = data if (movieIds) { this.movieIds = movieIds this.total = total return movieList } return coming }).then(data => { if (data.length) { this.offset += data.length this.movieList.push(...setImgSize(data)) $state.loaded() } else { $state.complete() } }) 复制代码
3 参数处理
const { offset, limit, total } = this const isFirst = offset === 0 if (offset && offset > total) return const movieIds = this.movieIds .slice(offset, offset + limit) .join() const params = { params: { ...this.params, movieIds } } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机程序设计艺术(第3卷)
Donald E.Knuth / 苏运霖 / 国防工业出版社 / 2002-9 / 98.00元
第3卷的头一次修订对经典计算机排序和查找技术做了最全面的考察。它扩充了第1卷对数据结构的处理,以将大小数据库和内外存储器一并考虑;遴选了精心核验的计算机方法,并对其效率做了定量分析。第3卷的突出特点是对“最优排序”一节的修订和对排列论与通用散列法的讨论。一起来看看 《计算机程序设计艺术(第3卷)》 这本书的介绍吧!