【问题标题】:Cancelling multiple API calls in Vue.js with Axios使用 Axios 在 Vue.js 中取消多个 API 调用
【发布时间】:2018-03-11 13:06:48
【问题描述】:

我正在开发一个包含多个“模块”的仪表板,每个模块都有自己的 API 调用。大多数端点都很快速,但有几个可能需要几秒钟。

我有一个日期范围的过滤选项,每次更改时我都会重新运行 API 调用数据。

问题是,如果用户在其他人加载之前不断快速更改日期范围,我不希望用户能够堆叠 API 调用。

我使用单个文件 vue 组件,并为每个 API 调用提供一个方法,然后使用一个方法对它们进行分组和调用。

watch: {
    dateFilter: function() {
        this.initStatModules();
    }
},
methods: {
    getCustomers: function() {
        var $this = this;
        return axios.get(`/api/v1/reports/${$this.team.id}/stats-dashboard/customers?date=${$this.dateFilter}`).then(function(response) {
            $this.customers = response.data;
        });
    },
    getBookings: function() {
        var $this = this;
        return axios.get(`/api/v1/reports/${$this.team.id}/stats-dashboard/bookings`).then(function(response) {
            $this.bookings = response.data;
        });
    },
    getTotalRevenue: function() {
        var $this = this;
        return axios.get(`/api/v1/reports/${$this.team.id}/services-revenue?date=${$this.dateFilter}`).then(function(response) {
            $this.totalRevenue = response.data.data.totalRevenue;
        });

    },
    initStatModules: function() {
        this.getCustomers();
        this.getBookings();
        this.getTotalRevenue();
    }
}

我希望能够在 watch 或 initStatModules 方法中取消所有待处理的 API 请求。

查看 axios 文档:https://github.com/axios/axios#cancellation 它受支持,但我无法按照自己的意愿实现它。

谢谢!

【问题讨论】:

    标签: ajax vue.js vuejs2 axios


    【解决方案1】:

    我建议避免调用而不是取消,Axios 说它是在草稿上实现的,在这种情况下,看起来避免调用就足够了。

    我的意思是:

    如果发生过滤器调用,不要让用户过滤。您还需要使用 async/await 或 Promises 来更好地控制它。

    例如,一个数据属性,如:

    isFiltering: false
    

    像你一样使用承诺(这里省略你的代码,但其他方法的想法相同):

    methods: {
      getCustomers: async function () {
          var $this = this;
          this.isFiltering = true;
          return axios.get(`/api/v1/reports/${$this.team.id}/stats-dashboard/customers?date=${$this.dateFilter}`).then(function(response) {
              $this.customers = response.data;
              $this.isFiltering = false;
          });
      }
    }
    

    在您的 HTML 中使用 isFiltering 来禁用(添加 CSS 或任何您希望的)输入。这将阻止用户更改过滤,并且看起来过滤正在执行。如果出现问题,请记住添加 .catch 部分以将 isFiltering 设置为 false。如果可用,使用.finally 会更好

    if isFiltering then disable

    另一种方法是使用 Lodash 中的 Throttle 或任何其他解决方案,或者在 S.O. 上建议的此实现:Simple throttle in js

    该限制选项更好地避免连续调用,例如当用户输入输入时。

    【讨论】:

    • 谢谢,这是我的备份选项,但您帮助解释了它。所有过滤都是通过下拉菜单完成的,所以我现在将禁用它们。希望 API 调用足够快,不需要太多,但我知道 Chrome 已经停止了几次。
    • 是的,我知道它是怎么回事。我确实同意,如果用户错误地选择了错误的输入(下拉选择),那么等待那么长时间会很烦人。但是 imo 阻止了它的更可测试和有保证的行为。因为我不想那么依赖取消行为。但最终它是你的电话。祝你好运=)
    【解决方案2】:
    <template>
      <input type="date" :disabled="isDisabled" v-model="dateFilter">
    </template>
    
    <script>
    export default {
      data () {
        return {
          dateFilter: null,
          modulesLoaded: 0,
          isDisabled: false
        }
      },
      watch: {
        dateFilter () {
          this.initStatModules()
        }
      },
      methods: {
        getCustomers () {
          axios.get(`/api/v1/reports/${$this.team.id}/stats-dashboard/customers?date=${$this.dateFilter}`)
            .then(response => {
              this.customers = response.data
              this.onModuleLoaded()
            })
        },
        getBookings () {
          axios.get(`/api/v1/reports/${$this.team.id}/stats-dashboard/bookings`)
            .then(response => {
              this.bookings = response.data
              this.onModuleLoaded()
            })
        },
        getTotalRevenue () {
          axios.get(`/api/v1/reports/${$this.team.id}/services-revenue?date=${$this.dateFilter}`)
            .then(response => {
              this.totalRevenue = response.data.data.totalRevenue
              this.onModuleLoaded()
            })
        },
        initStatModules () {
          this.isDisabled = true
          this.modulesLoaded = 0
          this.getCustomers()
          this.getBookings()
          this.getTotalRevenue()
        },
        onModuleLoaded () {
          this.modulesLoaded++
          if (this.modulesLoaded === 3) {
            this.isDisabled = false
          }
        }
      }
    }
    </script>
    

    试试这个。

    【讨论】:

    • 您应该避免仅使用代码的答案。请提供一些解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2021-01-31
    • 1970-01-01
    • 2021-11-17
    • 2021-01-18
    • 1970-01-01
    • 2019-04-21
    相关资源
    最近更新 更多