flyio 帮助文档

简介

Fly.js 是一个基于 promise 的,轻量且强大的Javascript http 网络库,它有如下特点:

  1. 提供统一的 Promise API。
  2. 浏览器环境下,轻量且非常轻量
  3. 支持多种JavaScript 运行环境
  4. 支持请求/响应拦截器。
  5. 自动转换 JSON 数据。
  6. 支持切换底层 Http Engine,可轻松适配各种运行环境
  7. 浏览器端支持全局Ajax拦截 。
  8. 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中引入的方式是一样的,下面是不同平台下的引入的方式:

  1. 浏览器、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. 在微信小程序中引入

    1
    2
    var Fly=require("flyio/dist/npm/wx")
    var fly=new Fly

    如果您的微信小程序项目没有使用npm来管理依赖,您可以直接下载源码到您的小程序工程,下载链接wx.jswx.umd.min.js .下载任意一个,保存到本地工程目录,假设在“lib”目录,接下来引入:

    1
    2
    var Fly=require("../lib/wx") 
    var fly=new Fly;
  1. 快应用中引入

    快应用 中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)
  1. Weex中引入

    1
    2
    var Fly=require("flyio/dist/npm/weex")
    var fly=new Fly

引入之后,您就可以对fly实例进行全局配置、添加拦截器、发起网络请求了。

具体实现实例

  1. 声明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',
    }
    }
    }
  2. 拦截器配置
    请求拦截器

    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)
    }
    )
    }
    // #endregion

    region 响应拦截器

    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
    8
    export class Http {
    constructor() {
    ...

    this.requestUse()
    this.responseUse()
    }
    }
  3. 实现请求队列loading或者静默请求
    首先定义队列属性

    1
    2
    3
    4
    5
    6
    export 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
    }
  4. 单例请求实现

    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
    34
      export 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 = {}}={}) {
    ...
    }
  5. 接口同步处理
    小程序中,一般会存在进入小程后必须先请求一个接口,请求其他接口时使用其返回的数据。此时我们可以用的拦截器锁定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
    25
    import { 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
2
3
4
5
 import request from '@/utils/http'

request({ url: url, data: data, silent: silent, options: options })

request( url, data, silent, options )