防止重复点击,在服务端未响应之前,多次请求数据

import axios from "axios";

const request = axios.create({
    baseURL:'http://localhost:3000',
    timeout:6000
})

// 发布订阅
class EventEmitter {
    constructor(){
        this.event = {} // 定义event对象的数据
    }

    // 往event对象中添加数据的方法
    on(type,cbres,cbrej){
        // 如果对象中不存在这个属性 便添加这个属性
        if(!this.event[type]){
            this.event[type] = [[cbres,cbrej]]
        }else{
            // 如果对象中存在这个属性就继续往这个对象中进行添加
            this.event[type].push([cbres,cbrej])
        }
    }

    emit(type,res,ansType){
        // 如果event中对象的属性不存在就停止执行后面的代码
        if(!this.event[type]){
            return false
        }else{
            // 如果存在 就将这个数据中对应的属性的值进行遍历,该对象属性值是一个数组,并且是一个数组包含数组的模式
            this.event[type].forEach(cbArr=>{
                if(ansType==='resolve'){
                    cbArr[0](res)
                }else{
                    cbArr[1](res)
                }
            })
        }
    }
}

// 根据请求生成对应的key
function generateReqkey(config,hash){
    const {method,url,params,data} = config
    return [method,url,JSON.stringify(params),JSON.stringify(data),hash].join('&')
}

// 存储已发送但未响应的请求
const pendingRequest = new Set()

// 发布订阅的容器
const ev = new EventEmitter()

// 请求拦截器
request.interceptors.request.use(async(config)=>{

    console.log(location)
    // 获取hash
    let hash = location.hash
    console.log('hahs',hash)

    // 生成请求的key
    let reqKey = generateReqkey(config,hash)
    console.log('key',reqKey)

    if(pendingRequest.has(reqKey)){
        // 如果已经存在相同的请求,在这里将请求挂起 通过发布订阅来为该请求返回结果
        // 这里需注意拿到结果后 无论成功是否 都需要return promise.reject()中断请求 否则请求将会正常发送服务器
        let res = null
        try{
            // 接口成功响应
            res = await new Promise((resolve,reject)=>{
                ev.on(reqKey,resolve,reject)
            })
            console.log(res)
            return Promise.reject({
                type:'limiteResSuccess',
                val:res
            })
        }catch(limitFunErr){
            // 接口报错
            return Promise.reject({
                type:'limiteResError',
                val:limitFunErr
            })
        }
    }else{
        config.pendKey = reqKey
        console.log('config',config)

        pendingRequest.add(reqKey)
        console.log(pendingRequest)
    }

    return config
},function(error){
    return Promise.reject(error)
})

// 添加响应拦截器
request.interceptors.response.use(function(response){

    console.log(response)
    // 将拿到的结果发布给其他相同的接口
    handleSuccessResponse_limit(response)

    return response
},function(error){
    return handleErrorResponse_limit(error)
})


// 接口响应成功
const handleSuccessResponse_limit = (response)=>{

    console.log(response)

    const reqKey = response.config.pendKey

    if(pendingRequest.has(reqKey)){

        console.log('存在吗')

        let x = null
        try{
            x = JSON.parse(JSON.stringify(response))

            console.log(x)

        }catch(e){
            x = response
        }
        pendingRequest.delete(reqKey)

        console.log(pendingRequest)

        ev.emit(reqKey,x,'resolve')

        delete ev.reqKey
    }
}

//  接口走失败的响应
function handleErrorResponse_limit(error){
    if(error.type&&error.type==='limiteResSuccess'){
        return Promise.resolve(error.val)
    }else if(error.type&&error.type==='limiteResError'){
        return Promise.reject(error.val)
    }else{
        const reqKey = error.config.pendKey
        if(pendingRequest.has(reqKey)){
            let x = null
            try{
                x = JSON.parse(JSON.stringify(error))
            }catch(e){
                x = error
            }
            pendingRequest.delete(reqKey)

            ev.emit(reqKey,x,'reject')

            delete ev.reqKey
        }
    }
    return Promise.reject(error)
}
export default request

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值