记一次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卷)

计算机程序设计艺术(第3卷)

Donald E.Knuth / 苏运霖 / 国防工业出版社 / 2002-9 / 98.00元

第3卷的头一次修订对经典计算机排序和查找技术做了最全面的考察。它扩充了第1卷对数据结构的处理,以将大小数据库和内外存储器一并考虑;遴选了精心核验的计算机方法,并对其效率做了定量分析。第3卷的突出特点是对“最优排序”一节的修订和对排列论与通用散列法的讨论。一起来看看 《计算机程序设计艺术(第3卷)》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换