Skip to content

竞态请求问题

竞态请求是指网络波动时,第二次请求的结果比第一次请求的结果先返回,常见于多个 Tab 页点击切换功能,如果用户点击频繁,很可能 会出现当前页面显示别的页面的数据。

解决方法

1. 交互层面解决

添加全局的 loading 遮罩,或者禁用查询按钮 ,这样的话,在第一个请求结果没返回之前不能发送第二个请求。

2. 取消请求

  • axios
js
const CancelToken = axios.CancelToken
let source

// 请求的函数
function query(keyword) {
  if (source) {
    source.cancel('取消请求')
  }
  source = CancelToken.source()

  return axios
    .post(
      '/list',
      {
        keyword,
      },
      {
        cancelToken: source.token,
      }
    )
    .catch(function (thrown) {
      // 区别处理取消请求和请求错误
      if (axios.isCancel(thrown)) {
        // 取消请求的逻辑
      } else {
        // 请求错误
      }
    })
}
  • Promise
js
let doCancel

// 请求的函数
function query(keyword) {
  if (doCancel) {
    // 设置上一次的 Promise 设为 rejected 状态
    doCancel('取消请求')
  }
  return new Promise(function (resolve, reject) {
    // 挂载 reject 方法
    doCancel = reject
    const xhr = new XMLHttpRequest()
    xhr.on('load', resolve)
    xhr.on('error', reject)
    xhr.open('POST', '/list', true)

    // 发送请求条件,这里未作处理
    xhr.send(null)
  }).catch(function (thrown) {
    // 区别处理取消请求和请求错误
    if (axios.isCancel(thrown)) {
      // 取消请求的逻辑
    } else {
      // 请求错误
    }
  })
}