【问题标题】:Vuex Store: Async Operations on Stale StateVuex Store:过时状态下的异步操作
【发布时间】:2021-08-02 07:45:41
【问题描述】:

我的 Vue 应用程序使用 Vuex 商店。有时用户可以“重置”会话。这需要将 vuex 存储重置为默认值,因此任何挂起的异步操作都应该被删除,因为 Vuex 存储已被重置。问题是当异步调用返回时,它们会尝试修改存储,但它已被重置。当用户点击“重置”时,如何强制忽略任何挂起的异步操作。

我想回顾一下“createStore”Vuex 函数,但这导致了死胡同,因为全局存储变量已更新。

编辑:我最终传递了一个带有每个突变的 StoreID。我将这个 StoreID 值存储在所有异步操作开头的变量中。突变验证何时调用商店当前处于相同的 StoreID 版本。有没有更聪明的方法来做到这一点?

【问题讨论】:

  • 这些异步操作是什么?它们是 API 调用吗?使用axios?
  • yes API 调用,例如在用户滚动时为表格获取数据。调用可能需要一段时间才能从服务器返回。
  • 如果你使用 axios,请勾选这个:stackoverflow.com/questions/38329209/…

标签: vue.js vuex vuex4


【解决方案1】:

您可以在解决/拒绝请求承诺之前将 StoreID 检查移至请求层。如果自发出请求后 StoreID 已更改,则通过不调用 resolve 或拒绝来忽略结果。这将允许您从商店的其余部分中删除支票,因为在您更新 StoreID 之前发送的请求永远不会调用突变。

如果您使用 axios 或具有取消请求能力的其他选项,则另一种选择是将所有挂起的请求取消令牌保存在一个数组中,并在您重置商店时将它们全部取消。这里的一个问题是,如果您的请求被拒绝的原因是因为它被取消了,您将需要检查您的请求错误处理。

axios.isCancel(err); // will be true if request was canceled

【讨论】:

    【解决方案2】:

    案例 1. 你正在使用 fetch:

    const controller = new AbortController();
    const {
      signal
    } = controller;
    
    actions: {
      fetchSoemthing(context, { url, options }) {
        fetch(url, {
          ...options,
          signal, //<------ This is our AbortSignal
        }).then(response => {
          console.log(`Request 1 is complete!`);
        }).catch(e => {
          console.warn(`Fetch 1 error: ${e.message}`);
        });
      },
      cancelAllRequests(context) {
        return controller.abort(); // in your usecase when you call the resetStoreData, you also dispatch this action.
      }
    }

    我不是 100% 确定信号是如何工作的,但我最好的建议是让您使用包装类进行 fetch 不要像这样直接在商店中使用它,而是在您当前的实现中尝试一下看看进展如何。

    案例2,你使用的是axios:

    import axios from "axios";
    
    const { CancelToken } = axios;
    const cancelToken = CancelToken.source();
    
    actions: {
      fetchSoemthing(context, {
        url,
        options
      }) {
        axios.post(url, options, {
            cancelToken,
          })
          .then((response) => {
            //responce Body
          })
          .catch((error) => {
            if (axios.isCancel(error)) {
              console.log("post Request canceled");
            }
          });
      },
      cancelAllRequests(context) {
        return cancelToken.cancel(); // in your usecase when you call the resetStoreData, you also dispatch this action.
      }
    }

    对于这两种实现,如果您想同时取消它们,您必须对每个请求使用相同的 canceltoken / 信号,因此我建议您在外部文件或 Vuex 状态中声明它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 2017-12-11
      • 2020-11-16
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多