当前位置 博文首页 > m0_45291815的博客:axios-ajax-WebSocket紧急救援

    m0_45291815的博客:axios-ajax-WebSocket紧急救援

    作者:[db:作者] 时间:2021-09-02 19:08

    接口交互效果

    1、ajax

    终止请求:abort()

    一个简单的ajax,仅供入门学习使用

    /**
     * 调用SendAjax,调用接口
     * @param {obj} object method:请求方式,url:地址,success:请求成功回调
     */
    
    function SendAjax (obj) {
        function createAJAX () {
            let ajax = null
            if (window.XMLHttpRequest) {
                ajax = new XMLHttpRequest() // iE7以上
            } else if (window.ActiveXObject) {
                const ActiveXObject = window.ActiveXObject // iE6到iE5以下
                ajax = new ActiveXObject('Microsoft.XMLHTTP')
            } else {
                alert('请升级浏览器')
            }
            return ajax
        }
        var ajax = createAJAX() // 创建一个ajax对象
        ajax.open(obj.method, obj.url, true)
        ajax.onreadystatechange = function () {
            if (ajax.readyState === 4 && ajax.status === 200) {
                obj.success(ajax.responseText)
            }
        }
        if (obj.method === 'get') {
            ajax.send(null)
        } else if (obj.method === 'post') {
            ajax.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
            let str = ''
            let v = ''
            let f = false
            for (var attr in obj.data) {
                str += v + attr + '=' + obj.data[attr]
                v = '&'
                if (obj.data[attr] !== '') {
                    f = true
                } else if (obj.data[attr] === '') {
                    f = false
                    return f
                }
            }
            if (f) {
                ajax.send(str)
            }
        }
    }
    
    export default SendAjax()
    

    2、JSONP

    跨越:协议,域名,端口号不同,引发的安全请求问题

    img标签的src可以解决上面的问题,但是请求回来的是图片信息,不能使用

    同理还有video标签等等

    script标签的src请求回来的是js代码信息,可以作为跨越解决方案

    但是返回的信息如何获取?可以通过函数调用的方式获取,调用函数,传入入参

    • 编写获取信息的回调函数
    • 同态生成script标签
    • 将请求地址+query传参方式将回调函数名称传给服务
    • 将生成的script标签前进给body
    • 服务将返回内容以callback(数据信息)的形式返回给浏览器
    • 实现跨越请求信息
    // 粗劣残暴的解决方案
    // params可以优化成对象
    /**
    * param { url } 跨越请求的地址
    * param { params } 拼接的字符串入参
    * param { fn } 获取返回结果的回调
    */
    export default function jsonp(url, params, fn) {
      let callbackName = `fn${+new Date()}`
      window[callbackName] = (res) => { fn(res) }
      let script = document.createElement('script')
      script.type = "text/javascript";
      script.src = `${url}?callback=${callbackName}&${params}`
      document.body.appendChild(script)
      document.body.removeChild(script)
    }
    

    3、axios

    实现功能:

    • post请求,get请求等基本请求

    • 请求前拦截,请求后拦击

    • 设置全局devServe识别标志(baseUrl),设置全局timeout响应时间

    • 拦截前操作:

      1. 添加全部baseUrl,可以单独接口自定义

      2. 添加全部timeout,可以单独接口自定义

      3. 通过store获取token,添加全局token,可以单独接口不需要定义

      4. 可以通过接口单独定义,将参数转表单格式

      5. 可以通过接口单独定义,设置下载文件名称

      6. 可以通过接口单独定义,添加获取下载/上传进度条的构造函数

      7. 创建接口关闭对象,并添加到storeapi请求控制队列 ----(?:未设计和验证)

        为了在切换路由时或特别情况时主动中断请求

    • 请求后拦截:

      1. 请求成功后将当前接口对象从api请求控制队列删除

      2. 判断接口数据是否为二进制图片流数据:是,就return二进制流转图片的链接

      3. 统一错误处理函数: ---- (?需要自己设置)

      4. 判断是否为未登录: ---- (?需要自己设置)

        是:统一报错,return false,并调整到登录页面

      5. 判断后端返回的状态码是否通过判断: ---- (?需要自己设置)

        是:返回结果,return data

        否:进入下一步

      6. 未通过判断,是否存在单独设置获取错误表示

        是:return Promise.reject(data)

        否:进行统一报错,return false

    • post请求形式下载

    • get请求形式下载

    • post转表单形式下载

    • jsonxlsx下载功能

    • post文件和数据分开上传

    • post文件和数据合成formData一起上传

    • xlsxjson导入功能

    可以直接复制,建议将代码看完后,修给后使用

    import axios from 'axios'
    import Qs from 'qs' // axios携带的插件,无序再次下载
    import XLSX from 'xlsx' // xlsx需要下载 npm install --save-dev xlsx
    import store from './store' // 引入vuex或redux或models 的数据管理
    
    /**
     * @params { timeout } number 请求超时时间,默认15s
     * @params { preFix } string 请求前缀,process.env.NODE_ENV === 'development' ? '/api' : '/gateway', 默认/api
     * @params { Message } function 错误统一处理函数, 参1:返回错误信息,参2:是否为未登录(默认false)
     * @params { baseURL } string 接口域名端口设置,默认空
     * @returns { ajax } object 返回接口请求对象
     * ajax对象, post, get, delete, patch 请求
     * export const a = (params) => ajax.post('/url', {
     *      ...params,
     *      baseUrl: '是否自定义前缀(如:/api),string'
     *      withoutToken: '是否添加token,boolean',
     *      transform: '是否转换为表单请求,boolean',
     *      timeout: '单独设置请求超时时间',number, 默认空
     *      setFileName: '自定义文件下载名称, string'
     *      getRange: 获取进度条(上传下载):Object: fn:回调函数,type判断上传upload还是下载download
     *      而且需要后端进行相关处理,否则获取不到文件大小total
     *
     *      gainError: '是否单独处理错误信息(会进行传递),boolean'
     * })
     * 文件下载和请求一样
     * ajax.downloadFileByPost post请求下载文件
     * ajax.downloadFileByGet get请求下载文件
     * ajax.downloadFileByForm 表单请求下载文件
     * @params { JsonData } json json数据格式
     * @params { columns } object 设置xlsx表头枚举
     * @params { FileName } 下载xlsx文件名称
     * ajax.jsonToXlsx json数据转xlsx(最简单的表格)下载 // 待验证
     * ajax.jsonToXlsx(JsonData, columns, FileName)
     *
     * 文件上传
     * @params { url, file, data }
     * ajax.uploadFile 文件上传 文件和数据分开
     * @params { url, params }
     * ajax.uploadFileWithPost 文件上传 文件和数据不分开
     * @params { file } file 上传的excel文件
     * @params { columns } json excel解析替换标题
     *  columns = [
            { label: '姓名', key: 'name' },
            { label: '电话', key: 'phone' },
            { label: '邮箱', key: 'email' }
        ]
     * ajax.xlsxToJson xlsx转json导入数据
     *
     * 获取上传文件方式
     * 1、原生
     * input type='file' @change=getFiles($event)
     * getFiles () { console.log(e.target.files) } 此时就可以拿到文件数据
     * 2、element
        <el-upload
            action="" // 请求地址设空
            accept=".xls,.xlsx"
            :auto-upload="false" // 禁止上传就请求
            :on-change="handleChange" // 通过on-change回调函数获取文件数据
        />
        handleChange (file) { this.file = file || null }
     * 3、ant design
     * 查看ant design 上传文档-手动上传
        beforeUpload (file) {
            this.setState(state => { fileList: [ ...fileList, file ] })
            return false // 返回false,终止自动上传
        }
     * 4、vant
       文件上传完毕后会触发 after-read 回调函数,获取到对应的 file 对象
     * 5、taro
     * 6、小程序
     * 使用小程序自带的上传组件
     *
     * @params { word } 终止返回文字提示
     * ajax请求中断 // 待验证
     * ajax.cancelAjax(word)
    */
    
    /* 使用实例
    const require = setAjax({
        timeout: 1000 * 60 * 10,
        preFix: '/api',
        Message: (msg, notLoading) => {},
        baseUrl: 127.0.0.1:8800
    })
    */
    
    function setAjax ({ timeout, preFix, Message, baseURL }) {
        /*
        * 基础请求get post delete patch
        * 通过请求拦截获取请求config,进行一下配置
        * 1、配置响应响应超时时间timeout
        * 2、配置不同情况下的请求地址baseUrl
        * 3、配置不同情况下的请求头headers
        */
    
        // 通过node变量,判断添加接口代理标志前缀
        // 其中/api是webpack-serve代理服务器的判别前缀,拥有代理
        // 另一个是后端的接口接入网关配置
        const prefix = preFix || '/api'
    
        const ajax = axios.create() // 实例化一个axios
    
        ajax.defaults.timeout = timeout || 1000 * 15 // 设置默认请求超时时间
        ajax.defaults.baseURL = baseURL || '' // 设置接口的地址和端口号
        let setFileName = false // 自定义文件下载名称
    
        // 添加代理识别/接口网关
        function getBaseUrl (config) {
            // 特定自定义过服务识别和网关接口,使用自定义的
            if (config.data && config.data.baseUrl) {
                config.url = config.data.baseUrl + config.url
                delete config.data.baseUrl // 删除请求时不必要的属性
            } else {
                // 否则使用环境变量判断得到的
                config.url = prefix + config.url
            }
            return config
        }
    
        // 添加token
        function addToken (config) {
            if (config.data.withoutToken) { // 如果注明不需要token,这不添加token,直接返回config对象
                delete config.data.withoutToken // 删除请求时不必要的属性
                return config
            }
            // 此时同步的是store里的token
            if (store.state.token && !config.headers.Authorization) config.headers.Authorization = store.state.token // 添加token
            return config
        }
    
        // 转换为表单格式请求
        function switchToFormData (config) {
            if (config.data && config.data.transform) { // 如果需要转换成表单格式
                delete config.data.transform // 删除请求时不必要的属性
                config.transformRequest = [ // 通过axios提供的transformRequest 修改入参格式
                    function (data) {
                        return Qs.stringify(data)
                    }
                ]
            }
            return config
        }
    
        // 单独设置超时时间
        function setTimeOut (config) {
            if (config.data && config.data.timeout) {
                ajax.defaults.timeout = config.data.timeout
                delete config.data.timeout
            }
            return config
        }
    
        // 设置下载文件名称
        function setDownFileName (config) {
            setFileName = false // 先重置下载文件名称
            if (config.data && config.data.setFileName) { // 如果存在自定义下载文件名称
                setFileName = config.data.setFileName
                delete config.data.setFileName
            }