微信公众号
扫描关注微信公众号
博客大厅

Pinia 如何处理异步操作?

原创 来源:博客站 阅读 0 03月22日 07:36 听全文

在 Pinia 中处理异步操作非常简单且灵活。Pinia 的 actions 支持同步和异步逻辑,因此你可以直接在 actions 中执行异步操作(如 API 请求、定时器等)。以下是处理异步操作的几种常见方式:


1. actions 中直接处理异步操作

你可以在 actions 中直接使用 async/awaitPromise 来处理异步操作。

示例:使用 async/await

// stores/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null as any,
    loading: false,
    error: null as string | null,
  }),
  actions: {
    async fetchUser(userId: number) {
      this.loading = true;
      this.error = null;

      try {
        const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
        if (!response.ok) {
          throw new Error('Failed to fetch user');
        }
        this.user = await response.json();
      } catch (error) {
        this.error = error instanceof Error ? error.message : 'Unknown error';
      } finally {
        this.loading = false;
      }
    },
  },
});

在组件中使用

<template>
  <div>
    <p v-if="userStore.loading">Loading...</p>
    <p v-else-if="userStore.error">Error: {{ userStore.error }}</p>
    <div v-else>
      <p>User: {{ userStore.user.name }}</p>
    </div>
    <button @click="fetchUser(1)">Fetch User</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { useUserStore } from '@/stores/user';

export default defineComponent({
  setup() {
    const userStore = useUserStore();

    function fetchUser(userId: number) {
      userStore.fetchUser(userId);
    }

    return {
      userStore,
      fetchUser,
    };
  },
});
</script>

2. 使用 Promise 处理异步操作

如果你更喜欢使用 Promise,也可以在 actions 中使用。

示例:使用 Promise

// stores/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null as any,
    loading: false,
    error: null as string | null,
  }),
  actions: {
    fetchUser(userId: number) {
      this.loading = true;
      this.error = null;

      fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
        .then((response) => {
          if (!response.ok) {
            throw new Error('Failed to fetch user');
          }
          return response.json();
        })
        .then((data) => {
          this.user = data;
        })
        .catch((error) => {
          this.error = error instanceof Error ? error.message : 'Unknown error';
        })
        .finally(() => {
          this.loading = false;
        });
    },
  },
});

3. actions 中调用其他 actions

你可以在一个 action 中调用另一个 action,以实现逻辑复用。

示例:调用其他 action

// stores/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null as any,
    loading: false,
    error: null as string | null,
  }),
  actions: {
    async fetchUser(userId: number) {
      this.loading = true;
      this.error = null;

      try {
        const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
        if (!response.ok) {
          throw new Error('Failed to fetch user');
        }
        this.user = await response.json();
      } catch (error) {
        this.setError(error);
      } finally {
        this.loading = false;
      }
    },
    setError(error: unknown) {
      this.error = error instanceof Error ? error.message : 'Unknown error';
    },
  },
});

4. 处理并行异步操作

如果需要并行执行多个异步操作,可以使用 Promise.all

示例:并行异步操作

// stores/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    users: [] as any[],
    loading: false,
    error: null as string | null,
  }),
  actions: {
    async fetchUsers(userIds: number[]) {
      this.loading = true;
      this.error = null;

      try {
        const promises = userIds.map((userId) =>
          fetch(`https://jsonplaceholder.typicode.com/users/${userId}`).then((response) => {
            if (!response.ok) {
              throw new Error('Failed to fetch user');
            }
            return response.json();
          })
        );
        this.users = await Promise.all(promises);
      } catch (error) {
        this.error = error instanceof Error ? error.message : 'Unknown error';
      } finally {
        this.loading = false;
      }
    },
  },
});

5. 取消异步操作

如果需要取消异步操作(如取消 API 请求),可以使用 AbortController

示例:取消异步操作

// stores/user.ts
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null as any,
    loading: false,
    error: null as string | null,
    abortController: null as AbortController | null,
  }),
  actions: {
    async fetchUser(userId: number) {
      if (this.abortController) {
        this.abortController.abort(); // 取消之前的请求
      }

      this.abortController = new AbortController();
      this.loading = true;
      this.error = null;

      try {
        const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, {
          signal: this.abortController.signal,
        });
        if (!response.ok) {
          throw new Error('Failed to fetch user');
        }
        this.user = await response.json();
      } catch (error) {
        if (error.name !== 'AbortError') {
          this.error = error instanceof Error ? error.message : 'Unknown error';
        }
      } finally {
        this.loading = false;
        this.abortController = null;
      }
    },
    cancelFetchUser() {
      if (this.abortController) {
        this.abortController.abort();
      }
    },
  },
});

6. 在组合式 API 中使用异步操作

如果使用组合式 API 定义 Store,可以直接在 setup 函数中处理异步操作。

示例:组合式 API 中的异步操作

// stores/user.ts
import { defineStore } from 'pinia';
import { ref } from 'vue';

export const useUserStore = defineStore('user', () => {
  const user = ref(null);
  const loading = ref(false);
  const error = ref<string | null>(null);

  async function fetchUser(userId: number) {
    loading.value = true;
    error.value = null;

    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
      if (!response.ok) {
        throw new Error('Failed to fetch user');
      }
      user.value = await response.json();
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Unknown error';
    } finally {
      loading.value = false;
    }
  }

  return {
    user,
    loading,
    error,
    fetchUser,
  };
});

总结

在 Pinia 中处理异步操作的方式包括:

  1. actions 中使用 async/awaitPromise
  2. 调用其他 actions 以实现逻辑复用。
  3. 使用 Promise.all 处理并行异步操作
  4. 使用 AbortController 取消异步操作
  5. 在组合式 API 中处理异步操作

Pinia 的灵活性使得处理异步操作变得非常简单,适合各种复杂场景。

学在每日,进无止境!更多精彩内容请关注微信公众号。
原文出处: 内容由AI生成仅供参考,请勿使用于商业用途。如若转载请注明原文及出处。
出处地址:http://www.07sucai.com/tech/835.html
版权声明:本文来源地址若非本站均为转载,若侵害到您的权利,请及时联系我们,我们会在第一时间进行处理。
>