6. Set和Map使用场景之一并发

152 阅读1分钟

如果使用Array,存在并发操作Array的情况, Array很难处理并发操作.

Set和Map天然支持并发!

Set相比Array优点, 用值删除而非索引

Map相比Array优点,用key删除,同时查找和删除的效率优于Array

下边例子我只处理了相同requestUrl的情况,没有继续判断data和params的原因是我担心增加data和params作为Map的key,会造成key长度过长,但经过网上查找,似乎js对Map单个key的长度并没有要求! 但总要有一个极限?

const tasksMap = new Map()

const service = axios.create({
  baseURL: config.serverUrl,
  timeout: 30000,
  validateStatus: function (status) {
    return status >= 200 && status < 300
  }
})

// request interceptor
service.interceptors.request.use(
  (config) => {
    const token = getToken()
   
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    
    debounceRequest(config)
    
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use((response) => {
  if(response.config.isDebounce) {
    tasksMap.delete(response.config.url)
  }
  return response.data
})

/**
 * 目前只简单校验requestUrl是否重复,没有校验data和params
 * @param {} config 
 * @returns 
 */
const debounceRequest = (config) => {
  const { isDebounce } = config
  if(!isDebounce) return

  config.requestStartTime = Date.now()
  const record = tasksMap.get(config.url)
  if(record) {
    if(Date.now() - record.requestStartTime < config.timeout) {
      console.warn('Request is debounced:', record.url)
      throw new Error('Request cancelled');
    } else {
      // 已超时, 应对断网时请求一直未出队的情况
      tasksMap.delete(config.url)
      tasksMap.set(config.url, config)
    }
  } else {
    tasksMap.set(config.url, config)
  }
}

export default service