记一次Promise在api接口合并中的实践
写在前面的话
- 本篇水文发出来之后,有朋友反馈文笔太差,的确是作者的锅,码字水平目前就这么高,只能委屈大家看这篇辣眼睛的文字了,文笔只能慢慢改善。
- 还有朋友反馈看懵的,仔细想想也是作者的锅,没有表达清楚,修改重发。
- 澄清一下本文和Promise.all没有半毛钱关系,如果让大家误会,见谅。
- 有朋友希望快速浏览能有一句总结,不想看代码。这里解释一下,其实总结就包含在下文合并接口的解释里,本文要解决的业务相对比较小众,脱离场景谈总结也没啥意义,不看业务场景和代码,本文真的没有任何的价值,主要是记录开发业务的一个思路。
关于接口合并(不知道有没有专门的术语,暂且如此称呼)在这里解释一下,本文所指的是页面初始化加载数据是一个api接口,而加载更多数据的是另一个api接口,前一个接口肯定会调用,第二个接口不一定会被调用(用户触发),但是我们把两个调用接口封装起来,公用一个业务逻辑,作者比较懒不想给两个接口分别写业务逻辑。
一. 前言
上次作者在个人项目中遇到的post预检请求bug,水了一篇小文《记一次跨域post请求数据之preflight request》,本文也只是记录在特定项目中如何抽取业务逻辑,封装两个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 | 电影总数目, total >= movieList.length |
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 获取当前热映更多电影列表
以下都将以 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。
有朋友关注api_2接口依赖于api_1接口,猫眼的api就是这么设计的,api_1接口返回了部分电影列表、全部的电影id和电影总数,api_2接口请求只需传递电影id就可以了。其他公司设计的api接口请求参数可能就是offset和limit。
三. 方案
要进行接口合并,无非要解决两个问题, 判断接口、处理数据
1 判断接口
api_2接口请求数据的时候必定需要知道请求的是那些电影的ID,那么我们肯定要在本地定义一个offset作为数据的偏移量,作者的项目是vue写的,就放在了vue的组件实例上了。我们将offset设为0,第一次请求时offset必定为0,我们就将offset的值作为判断接口的依据。
下面直接上代码
/***
* 业务逻辑部分
* 1. isFirst判断是否第一次请求
* 2. getInfoListAction(isFirst) 得到最终的api操作函数 getMovieInfoList
* 关于 getInfoListAction请参看下文 @src src\api\index.js
***/
import { getInfoListAction } from '@/api'const { offset, limit, total } = this
const isFirst = offset === 0
const getMovieInfoList = getInfoListAction(isFirst)
getMovieInfoList(params).then(data => {// ....数据处理此处略,详见下文
})
复制代码
难道直接用if-esle来硬编码判断?作者当然不会这么糊弄大家了。
/**
* @addr src/api/index.js
* @ getMovieOnInfoList 初始api的操作函数
* @ getMoreComingList 加载更多数据的操作函数
* @ getInfoListAction通过上文的isFirst作为参数调用来判断返回 getMovieOnInfoList还是 getMoreComingList(也就是上文提到的getMovieInfoList)* 关于 getDataByAction 参看下文 @addr src/util/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
* @getDataByAction 使用函数柯里化,接受两个操作函数返回一个新函数,在业务逻辑中返回最终的api操作函数
**/
export const getDataByAction = (initAction, nextAction) => (isFirst) => isFirst ? initAction : nextAction// @addr src/util/request.js
import Axios from 'axios'
let baseURL = process.env.VUE_APP_URLconst defaultConfig = {baseURL
}const STATUS_CODE = 200const 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.1、2.2我们获得了最后的数据Array,判断数据的长度,更新offset偏移量和movieList数据
* ps: setImgSize是处理图片的函数,不必理会
**/
getMovieInfoList(params).then(data => {const { movieIds, movieList, coming, total } = dataif (movieIds) {this.movieIds = movieIdsthis.total = totalreturn movieList}return coming
}).then(data => {if (data.length) {this.offset += data.lengththis.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 } }
复制代码
结尾
水到现在终于要结束了,挤一挤好像也没啥干货,关于接口合并,智者见智,万一以后改接口爆炸了也说不定,作者只是记录下当前遇到类似情况的一种处理方案,或者有更好的方案欢迎大家分享,行文错漏、改善之处欢迎提出来探讨。
Tips: 每天水一篇,生活乐无边。
转载于:https://juejin.im/post/5c80b548518825407b2b64a4
记一次Promise在api接口合并中的实践相关推荐
- 搭建股票数据api接口过程中会遇到什么问题?
搭建股票数据api接口过程中会遇到什么问题?以下这些问题比较常见,对于可能出现问题,建议每个搭建者最好能够提前了解并掌握更好的解决方案,从而应对可能出现的潜在问题. 拉合作方还是推数据? 股票数据ap ...
- python实现简单的api接口-python中接口的实现实例
接口基础知识: 简单说下接口测试,现在常用的2种接口就是http api和rpc协议的接口,今天主要说:http api接口是走http协议通过路径来区分调用的方法,请求报文格式都是key-value ...
- api接口加密_谈谈API接口开发中的安全性如何解决
如今各种API接口层出不穷,一个API的好与不好可以从很多方面来考量,其中"安全性"就是一个API接口最基本也是最重要的一个特点.本文就来跟大家聊聊关于API接口开发的安全性问题. ...
- API 接口设计中 Token 类型的分类与设计
在实际的网站设计中我们经常会遇到用户数据的验证和加密的问题,如果实现单点,如果保证数据准确,如何放着重放,如何防止CSRF等等 其中,在所有的服务设计中,都不可避免的涉及到Token的设计. 目前,基 ...
- 网站直达上线运营,API接口开发中
为什么80%的码农都做不了架构师?>>> 今天(2014-4-14)开通的企业三剑客 的药店直达(http://store.yi18.net) 于是组成了 医药企业的三剑客 医 ...
- 超详细讲解大事件项目api接口
文章目录 1. 初始化 1.1新建项目 1.2 配置 cors 跨域 1.3 配置解析表单数据的中间件 1.4 初始化路由相关的文件夹 1.5 初始化用户路由模块 1.6 抽离用户路由模块中的处理函数 ...
- API接口设计 注意问题
摘要: 总结一下API接口开发过程中的注意事项 1.跨平台性 所谓跨平台是指我们的接口要能够支持不同的终端,比如Android.iOS.windowsphone以及桌面软件.网站等.如:不同的终端每页 ...
- 新浪短网址生成java_新浪短链接 推荐几个最新的新浪t.cn短链接生成的API接口
新浪很久之前提供了长链接转为短链接的公开API,可以把长链接转为t.cn/xxx这种格式的新浪短链接.但是在去年9月的时候,新浪由于政策上的调整,将之前的接口关闭了! 今天就给大家带来几个还可以使用新 ...
- 最新智云全能API接口查询PHP源码V1.1
介绍: 1.[一言/随机语录]2.[必应每日一图]3.[域名是否已注册查询接口]4.[m3u8视频在线解析]5.[随机生成二次元图片]6.[快递查询-支持国内百家快递]7.[二维码图片生成]8.[抖音 ...
最新文章
- Spring Cloud构建微服务架构:服务消费(Feign)【Dalston版】
- c语言如何监控网卡信息,查看网卡信息及状态和网卡日志信息
- 0-MyBatis简介
- ZooKeeper之Web管理工具Shepher介绍
- WPF的ListBox的数据绑定,但需要添加控件在里面的时候
- 报告一下近期读书情况
- VB讲课笔记13:二级公共基础
- Java动态代理之InvocationHandler最简单的入门教程 1
- Java学习日记之 Java-IO流
- 区块链底层平台有哪些 区块链底层平台搭建
- java integer转成负数_Java 十进制和十六制之间的转化(负数的处理)
- cesium实现立体墙(垂直、水平)渐变泛光效果
- 人工智能研究的内容:_更深入:人工智能研究的思想史
- Siemens Simcenter FloEFD 2021.2.0 for Catia V5
- Android 6.0 更新包与已安装应用的签名不一致
- 【Android】打包生成APK教程
- what Data Fabric
- Ubutntu下使用realsense d435i(三):使用yolo v5测量目标物中心点三维坐标
- 含论文+辩论PPT+源码等]微信小程序ssm社区心理健康服务平台+后台管理系统
- 风丘科技为您提供10M以太网解决方案
热门文章
- 推特的id生成器的使用
- 如何使用Globus从NCAR官网上下载JRA55数据
- iPhone 5S及iWatch或将采用指纹验证技术
- Python实现照片卡通化,一拳打破次元壁 | 机器学习
- matlab 线性索引 转换,自己编写的 matlab 线性索引转换下标 函数
- php 如何输出一张图片,PHP 生成一张图片的两种方法
- 从零起步(无需数学和Python基础)编码实现AI框架之第六节课:使用Matrix编写AI框架实战及测试
- java jdbcrdd_鸡肋的JdbcRDD
- windows电脑离线安装mysql 8_windows环境下手动安装Mysql8
- poj2236 Wireless Network