需求:

  • tabs切换时,调用相同接口(参数不同)渲染图表数据。(每 3s 请求一次)

存在问题:

  • 在tabs切换的时候,因为定时器的原因,接口数据仍在pending,导致切换之后的图表第一条数据仍为上一个tabs的数据

解决方案:

  • 第二次请求接口时,取消上一次请求。axios官方手册
  • 第一次未结束,不允许第二次请求
  • 定义一个变量,判断此时tabs是否切换,做对应的数据渲染

在这里插入图片描述

具体js实现:

  1. 取消上一次接口请求

在这里插入图片描述

  • 实现细节
import axios from 'axios'
export default {
  name: 'chart',
  data () {
    return {
      relChartData: {},
      source: null
    }
  },
  beforeDestroy () {
    if (this.timer != null) {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  methods: {
    handleUnit (type) {
      switch (type) {
        case 'tps':
          return '次/秒'
        default:
          return ''
      }
    },
    hanndleData (data, type) {
      const unit = this.handleUnit(type)
      const temp = {
        config: {}
      }
      Object.keys(data.series).forEach((item) => {
        temp.config[item] = {
          unit
        }
      })
      const result = { ...data, ...temp }
      return result
    },
    async realData (type) {
      // 取消上一次请求
      this.cancelRequest()
      await axios({
        method: 'post',
        url: '/user/12345',
        data: { name: '小白' },
        cancelToken: new axios.CancelToken((c) => {
          this.source = c
        })
      })
        .then((res) => {
          //  返回数据进行操作
          this.relChartData = this.hanndleData(res.data, type)
        }).catch((err) => {
          if (axios.isCancel(err)) {
          // 请求如果被取消
            console.log('Rquest canceled')
          } else {
            console.log(err)
          }
        })
    },
    cancelRequest () {
      if (typeof this.source === 'function') {
        this.source()
      }
    },
    // 实时数据,显示类型改变时
    realChartChangeRadio (type) {
      this.chartType = type
      if (this.timer) {
        this.relChartData = {}
        clearInterval(this.timer)
        this.timer = null
      }
      this.realData(type)
      this.timer = setInterval(() => {
        this.realData(type)
      }, 3000)
    },
  }
}

  1. 变量判断tab切换
import axios from 'axios'
export default {
  name: 'chart',
  data () {
    return {
      relChartData: {},
      tabState: true // tab切换的状态
    }
  },
  beforeDestroy () {
    if (this.timer != null) {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  methods: {
    hanndleData (data, type) {
      const unit = this.handleUnit(type)
      const temp = {
        config: {}
      }
      Object.keys(data.series).forEach((item) => {
        temp.config[item] = {
          unit
        }
      })
      const result = { ...data, ...temp }
      return result
    },
    async realData (type) {
      await axios.post('user/1234').then(res => {
        if (this.tabState) {
          this.relChartData = this.hanndleData(res.data, type)
        } else {
          this.tabState = true
        }
      }).catch(err => {
        console.log(err)
      })
    },
    // 实时数据,显示类型改变时
    realChartChangeRadio (type) {
      console.log('切换了')
      this.chartType = type
      if (this.timer) {
        this.relChartData = {}
        this.tabState = false
        clearInterval(this.timer)
        this.timer = null
      }
      this.realData(type)
      this.timer = setInterval(() => {
        this.realData(type)
      }, 3000)
    },
    handleUnit (type) {
      switch (type) {
        case 'TPS':
        case 'tps':
          return '次/秒'
        default:
          return ''
      }
    }
  }
}

-----------------------------------------------------------------------------------------------------------------------

上面的两种方案均有各自的缺陷,方案1只要在有新的请求发起的时候,就取消上一个请求,可能导致多次cancel,而页面中长时间没有数据展示;方案2只针对,接口中只有一个请求的时候,可保证切换之后的单位正常显示,当有多个pending中的请求时(即上面的tabs切换过快),还是会出现偶尔的格式错乱的情况。

因此:最好的解决方案是:提前记录所有的网络请求。在tabs切换时,取消仍在pending中的网络请求即可

实现效果:
在这里插入图片描述

import axios from 'axios'
export default {
  name: 'chart',
  data () {
    return {
      relChartData: {},
      source: null,
      requestList: [] // 记录所有的网络请求。在tabs切换时,取消仍在pending中的网络请求
    }
  },
  beforeDestroy () {
    if (this.timer != null) {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  methods: {
    handleUnit (type) {
      switch (type) {
        case 'tps':
          return '次/秒'
        default:
          return ''
      }
    },
    hanndleData (data, type) {
      const unit = this.handleUnit(type)
      const temp = {
        config: {}
      }
      Object.keys(data.series).forEach((item) => {
        temp.config[item] = {
          unit
        }
      })
      const result = { ...data, ...temp }
      return result
    },
    async realData (type) {
      await axios({
        method: 'post',
        url: '/user/12345',
        data: { name: '小白' },
        cancelToken: new axios.CancelToken((c) => {
          this.source = c
          this.requestList.push(c)
        })
      })
        .then((res) => {
          //  返回数据进行操作
          this.relChartData = this.hanndleData(res.data, type)
        }).catch((err) => {
          if (axios.isCancel(err)) {
          // 请求如果被取消
            console.log('Rquest canceled')
          } else {
            console.log(err)
          }
        })
    },
    // 实时数据,显示类型改变时
    realChartChangeRadio (type) {
      this.chartType = type
      if (this.timer) {
        console.log('切换了显示类型,将仍在pending中的请求全部取消')
        this.relChartData = {}
        // 方案2: 在切换时,取消所有的pending请求
        this.requestList.forEach((cancelFunc, index) => {
          cancelFunc()
        })
        this.requestList = []
        clearInterval(this.timer)
        this.timer = null
      }
      this.realData(type)
      this.timer = setInterval(() => {
        this.realData(type)
      }, 3000)
    },
  }
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐