uniapp 中使用fly
简介
Fly.js 是一个基于 promise 的,轻量且强大的Javascript http 网络库,它有如下特点:
- 提供统一的 Promise API。
- 浏览器环境下,轻量且非常轻量 。
- 支持多种JavaScript 运行环境
- 支持请求/响应拦截器。
- 自动转换 JSON 数据。
- 支持切换底层 Http Engine,可轻松适配各种运行环境。
- 浏览器端支持全局Ajax拦截 。
- H5页面内嵌到原生 APP 中时,支持将 http 请求转发到 Native。支持直接请求图片。
安装
使用NPM
1 | npm install flyio |
使用CDN(浏览器中)
1 | <script src="https://unpkg.com/flyio/dist/fly.min.js"></script> |
UMD(浏览器中)
1 | https://unpkg.com/flyio/dist/umd/fly.umd.min.js |
引入flyio
不同JavaScript运行时的入口文件不同 ,请查看文档后面相应平台的引入方式,但在浏览器、Node、React Native中引入的方式是一样的,下面是不同平台下的引入的方式:
浏览器、Node、React Native中引入
1
2
var fly=require("flyio")上面方式引入的是Fly的默认实例(浏览器、Node、React Native中相同),你也可以自己创建Fly实例:
1
2
3
4
5
var Fly=require("flyio/dist/npm/fly")
var fly=new Fly;
在微信小程序中引入
1
2var Fly=require("flyio/dist/npm/wx")
var fly=new Fly如果您的微信小程序项目没有使用
npm
来管理依赖,您可以直接下载源码到您的小程序工程,下载链接wx.js 或 wx.umd.min.js .下载任意一个,保存到本地工程目录,假设在“lib”目录,接下来引入:1
2var Fly=require("../lib/wx")
var fly=new Fly;
快应用中引入
快应用 中Fly依赖
fetch
模块,需要先在manifest.json
中添加引用:1
2
3
4"features": [
...
{"name": "system.fetch"}
]然后创建fly实例
1
2
3
4
var fetch = require("@system.fetch")
var Fly=require("flyio/dist/npm/hap")
var fly=new Fly(fetch)
Weex中引入
1
2var Fly=require("flyio/dist/npm/weex")
var fly=new Fly
引入之后,您就可以对fly实例进行全局配置、添加拦截器、发起网络请求了。
具体实现实例
声明fly实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/**
* Http
*
* @export
* @class Http
*/
/* eslint-disable */
export class Http {
constructor() {
let Fly = require('flyio') // https://wendux.github.io/dist/#/doc/flyio/readme
// #ifdef MP-WEIXIN
Fly = require('flyio/dist/npm/wx') // https://wendux.github.io/dist/#/doc/flyio/readme
// #endif
this.instance = new Fly()
this.instance.config= {
baseURL: process.env.VUE_APP_API // 环境变量中定义的api域名
'Content-Type': 'application/json;charset=UTF-8',
}
}
}拦截器配置
请求拦截器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// #region 请求拦截器
requestUse () {
this.instance.interceptors.request.use(
request => {
request.headers = {
'zpinno-boleuid': store.state.boleUid, // 必传参数放在headers 实现
...request.headers
}
console.info(`🔊 [请求拦截器] -> ${request.url}`, request, 'request')
return request
},
error => {
console.error('🔊 [请求拦截器] -> error', error)
return Promise.resolve(error)
}
)
}
// #endregionregion 响应拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// #region 响应拦截器
responseUse () {
this.instance.interceptors.response.use(
response => {
console.info(`🔊 [响应拦截器] -> ${response.request.url}`, response)
return Promise.resolve(response.data)
},
error => {
console.info(`🔊 [响应拦截器] -> error -> ${error.request.url}`, error)
// #region response status: 请求已发出,但是不在2xx的范围
const statusCode = {
404: '404,错误请求',
401: '未授权',
403: '禁止访问',
408: '请求超时',
500: '服务器内部错误',
501: '功能未实现',
502: '服务不可用',
503: '服务不可用',
504: '网关错误',
510: '服务器内部错误'
}
// #endregion
// TODO 处理断网的情况
const statusMessage = statusCode[~~error.response.status]
return Promise.reject(statusMessage ? new Error(statusMessage) : error)
}
)
}
// #endregion引用拦截器
1
2
3
4
5
6
7
8export class Http {
constructor() {
...
this.requestUse()
this.responseUse()
}
}实现请求队列
loading
或者静默请求
首先定义队列属性1
2
3
4
5
6export class Http {
constructor() {
...
this._requestList = [] // 请求队列
}通过get set 实现监听requestList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// #region 请求队列 get set
get requestList () {
return this._requestList
}
set requestList (list) {
this._requestList = list // 设置请求队列
if (this._requestList.length === 0) {
// 如果请求队列为空了,就关闭loading
uni.hideLoading()
} else {
// 反知显示loading
uni.showLoading({
title: '加载中'
})
}
}
// #endregion入队出队方法
1
2
3
4
5
6
7
8
9
10/**
*
* @param {String} id 请求队列入队或出队的id
* @param {Boolean} remove true: 出队 false: 默认 进队
*/
setRequestList ({ id = '', remove = false } = {}) {
const array = [...this._requestList]
remove ? array.splice(array.indexOf(id), 1) : array.push(id)
this.requestList = array
}单例请求实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34export const http = new Http()
// #region 单例请求接口
/**
*
* @param {String} url 请求url
* @param {Object} data 请求参数
* @param {Object} options 请求参数
* @param {Boolean} silent true: 静默 false: loading
* @param {Object} options 配置
*/
export default function request (url = '', data = {}, silent = false, options = {}) {
const id = `${url}TIME${new Date().getTime()}` // 生成id
!silent && http.setRequestList({ id })
return new Promise((resolve, reject) => {
http.instance
.request(url, data, {
method: 'get',
...options
})
.then(res => {
http.setRequestList({ el: id, remove: true }) // 请求完成后,出队
resolve(res)
})
.catch(error => {
http.setRequestList({ el: id, remove: true }) // 请求完成后,出队
reject(error)
})
})
},
// #endregion参数对象方式传入
1
2
3
4
5
6
7
8
9
10
11
12...
/**
*
* @param {String} url 请求url
* @param {Object} data 请求参数
* @param {Object} options 请求参数
* @param {Boolean} silent true: 静默 false: loading
* @param {Object} options 配置
*/
export default function request ({url = '', data = {}, silent = false, options = {}}={}) {
...
}接口同步处理
小程序中,一般会存在进入小程后必须先请求一个接口,请求其他接口时使用其返回的数据。此时我们可以用的拦截器锁定API拦截器锁定API
请求拦截器和响应拦截器都提供了锁定自身的API, 拦截器锁定后,未进入到该拦截器的请求将在拦截器外面排队,暂停网络请求,直到拦截器解锁时,排队的请求才再次进入拦截器继续请求。请求拦截器和响应拦截器都提供了如下两个API:
lock()
锁定当前拦截器是。
unlock
解锁当前拦截器。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import { http, Http } from '@/utils/http'
async wxDecrypt({ state, commit }) {
http.instance.lock() //锁定当前拦截器是。
const authHttp = new Http()
uni.login({
provider: 'weixin',
//获取code 使用wx.login得到的登陆凭证,用于换取openid
success: async resLogin => {
const res = await authHttp.instance.post(url, {
jsCode: resLogin.code,
appletName: appletName,
parentSignature: state.parentSignature,
shareId: state.globalScene
})
// 更新headers配置
http.instance.config.headers = {
...http.instance.config.headers,
'uid': res.data.Uid
}
http.instance.unlock() //解锁当前拦截器。
}
})
},
使用示例
1 | import request from '@/utils/http' |