【问题标题】:Stop Axios Requests On Route Change with Mobx State Tree?使用 Mobx 状态树在路由更改时停止 Axios 请求?
【发布时间】:2019-06-11 16:41:51
【问题描述】:

我正在使用 axios,我注意到有人去 Route A 然后快速点击一个按钮到 Route B Route A 请求仍然会运行,并且可能会发生奇怪的结果。

我正在做这样的事情

getAllTaxRates: flow(function*() {
  try {

      const response = yield self.rootStore().axios.get('/get');

      applySnapshot(self.taxRates, response.data);

  } catch (error) {
    throw error;
  }
}),

所以我不确定取消这些请求的最佳方法是什么。

【问题讨论】:

    标签: reactjs react-router mobx mobx-state-tree


    【解决方案1】:

    我在这里遇到了同样的问题。其实不完全。只是我的架构容易受到同样类型的问题的影响(现在我正在考虑它)。我想我们应该做的是存储路由器的状态(可能在volatile state)并在尝试请求任何路由之前咨询它。然后,如果有必要,我们可以停止更改路由,或者取消之前的请求(并且应该通过可取消的实用程序发出请求),然后再创建一个新请求。

    您还可以add a middleware 可以在任何阶段取消异步操作。因此,您可能会在操作的每个阶段咨询上述标志,并在检测到冲突时退出。但这不会停止请求本身。

    第三个选项也是我猜的最好的一个选项,是为每个请求创建一个不稳定的状态,带有一个状态和对实际请求的引用,以便它可以在销毁时自动取消它。一旦您将新请求分配给树上的同一节点,就会触发销毁。

    【讨论】:

      【解决方案2】:

      您可以使用 axios 提供的a Cancel Token 在新请求开始时取消挂起的请求(然后每次我想您都必须创建一个新令牌)。

      但是我记得那个方法有一些问题(它冻结了我的整个应用程序),我最终使用了 Node-Fetch 和 AbortController,它非常适合我的使用。 (见this answer

      编辑: 这是我的大致做法,请注意我的请求函数是异步的(使用 Context API,但你应该能够对 Mobx 做同样的事情)

      import React from 'react';
      import Context from './Context';
      import fetch from 'node-fetch';
      
      class Provider extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            isLoading: false,
            controller: new AbortController(),
          };
          this.queryAll = this.queryAll.bind(this);
          this.abortAllRequest = this.abortAllRequest.bind(this);
        }
      
        abortAllRequest() {
          this.state.controller.abort();
          this.setState({
            isLoading: false,
            controller: new AbortController(),
          });
        }
      
        async queryAll(eans) {
          if (this.state.isLoading) {
            await this.abortAllRequest();
          }
      
          const signal = this.state.controller.signal;
      
          const result = await fetch(`/SomUrl/`, {
            method: 'get',
            signal: signal,
          });
        }
      
        render() {
          return (
            <Context.Provider value={{
              state: this.state,
              queryAll: this.queryAll,
              abortAllRequest: this.abortAllRequest,
            }}>
              {this.props.children}
            </Context.Provider>
          );
        }
      }
      
      export default Provider;

      【讨论】:

      • 是的,我看到了,但我想我必须在函数之外制作这个令牌并将其传递进去?因为我不确定我会将它存储在哪里,并且每个请求都需要它自己的吗?比如说页面触发了 5 个请求,我可以对所有 5 个请求使用相同的令牌吗?
      • 如前所述,我不确定它如何与 Axios 一起使用。使用 node-fetch,您可以为所有请求使用一个 AbortController,但是每次您在前一个上调用 .abort() 时都必须创建一个新的 AbortController,然后您可以将其存储在状态中
      猜你喜欢
      • 2021-05-19
      • 2018-12-28
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      • 2017-12-19
      • 2019-03-13
      • 2016-10-21
      • 2018-12-18
      相关资源
      最近更新 更多