首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将onMounted中定义的const提供给上下文

将onMounted中定义的const提供给上下文
EN

Stack Overflow用户
提问于 2022-06-02 08:06:35
回答 1查看 248关注 0票数 1

我所面临的情况是,我需要创建一个API调用,但在组件挂载之前不应该触发它。

这就是我到目前为止得到的:

代码语言:javascript
运行
复制
onMounted(async() => {
    const {
        data,
        refresh,
        pending,
        error
    } = await useApi(`/profile/${$auth.user.profile.sid}`, null, ['data']);

});

const computedWaiting = computed<boolean>(() => {
    return pending.value === true;
});

现在的问题是,computedWaiting抛出一个错误,因为没有定义pending。所以我需要销毁useApi-response,它基本上是一个https://github.com/unjs/ohmyfetch-result

这是useApi方法(摘自这个GitHub-发行版:https://github.com/nuxt/framework/discussions/4504):

代码语言:javascript
运行
复制
import {FetchOptions} from "ohmyfetch";

const csrf_cookie: string = "XSRF-TOKEN";

/**
 * Return the cookies needed by "Sanctum", browser will handle them automatically.
 */
export const useFetchCookies = async () => {

    await $fetch.raw("/backend/sanctum/csrf-cookie", {
        credentials: "include" // Allow browser to handle cookies
    });
};

/**
 * Api call using nuxt `useFetch`
 *
 * @see {@link https://github.com/unjs/ohmyfetch#readme} ~ ohmyfetch Docs
 * @param url
 * @param options
 * @param pick
 */
export const useApi = async (url: string, options?: FetchOptions, pick?: any) => {

    // First we verify if the `xsrf-token` is present on the browser cookies
    let token = useCookie(csrf_cookie)?.value;

    if (!token) {
        // If not present we will re fetch all cookies, the browser will
        // handle them automatically so we don't need to do anything
        await useFetchCookies();

        // Load the new token value to use it in the `headers`
        token = useCookie(csrf_cookie).value;
    }

    // Here we will create a default set of headers for every request
    // if present we will also spread the `headers` set by the user
    // then we will delete them to avoid collision in next spread
    const headers: HeadersInit = {
        Accept: "application/json",
        "Cache-Control": "no-cache",
        "X-XSRF-TOKEN": token,
        ...options?.headers
    };

    // At this point all the `headers` passed by the user where correctly
    // set in the defaults, now we will spread `options` to remove the
    // `headers` attribute so we don't spread it again in `useFetch`
    const opts: FetchOptions = options ? (({headers, ...opts}) => opts)(options) : null;

    return useLazyFetch(`/backend/api${url}`, {
        server: false,
        credentials: "include", // Allow browser to handle cookies
        headers,
        ...opts,
        pick: pick
    });

};

知道useFetch来自https://v3.nuxtjs.org/guide/features/data-fetching可能会有帮助,它基本上使用ohmyfetch作为可组合的自身:https://github.com/nuxt/framework/blob/46c656c4b85c3622b99a7c4f6a01f5b11c830be6/packages/nuxt/src/app/composables/fetch.ts#L18-L59

那么,怎样才能在datarefreshpendingerror之后最优雅地公开onMounted呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-02 10:53:07

在没有特定用途的情况下,在onMounted中调用一个可组合的是不正确的。Vue可组合通常直接在安装函数中使用,因此可以立即访问结果。能否在其他地方使用它们取决于它们的实现。

如果可组合涉及异步副作用,则应该返回反应性结果,返回结果的承诺将限制其使用。useFetch是Nuxt可组合的,它返回一个承诺,似乎是为了在Nuxt生命周期挂钩中使用,而useLazyFetch是通用的Vue可组合。

这在the usage of useLazyFetch中得到了显示,结果的属性是参考的,所以是反应性的。如果它被自定义可组合封装,则来自useLazyFetch的结果需要通过Vue组合API来组合,例如,pending应该反映当前操作的总体状态。

useFetchCookiesuseApi都需要更改为传统的可组合性。

代码语言:javascript
运行
复制
export const useToken = () => {
    const data = ref(null);
    const error = ref(null);
    const pending = ref(true);
    const token = useCookie(csrf_cookie).value;

    if (!token) {
      const result = useLazyFetch("/backend/sanctum/csrf-cookie", {
        credentials: "include" 
      });

      watch(result.pending, (val) => {
        pending.value = val;

        if (!val)
          data.value = useCookie(csrf_cookie).value;
      });

      watch(result.error, (val) => {
        error.value = val;
      });
    } else {
      pending.value = false;
      data.value = useCookie(csrf_cookie).value;
    }

    return { data, error, pending };
};
代码语言:javascript
运行
复制
export const useApi = (url: string, options?: FetchOptions, pick?: any) => {
    const data = ref(null);
    const error = ref(null);
    const pending = ref(true);
    const refresh = () => fetchResult.value?.refresh();
    
    const fetchResultRef = ref(null);

    const tokenResult = useToken();

      watch(tokenResult.data, (token) => {
        if (!token)
          return;

        const headers = ...;
        const opts = ...;    
        fetchResultRef.value = useLazyFetch(`/backend/api${url}`, {
            server: false,
            credentials: "include",
            headers,
            ...opts,
            pick: pick
        });
      });

      watch([
        tokenResult.pending,
        () => fetchResultRef.value?.pending ?? true
      ], ([tokenPending, fetchPending]) => {
        pending.value = tokenPending || fetchPending;
      });

      watch([
        tokenResult.error,
        () => fetchResultRef.value?.error ?? null
      ], ([tokenError, fetchError]) => {
        error.value = tokenError || fetchError;
      });

      watch(() => fetchResultRef.value?.data ?? null, (value) => {
        data.value = value;
      });

      return { data, error, pending, refresh };
};

请注意,在此实现中,useCookie结果是反应性的,但反应性被丢弃,因此useToken中的refresh仍未使用。useLazyFetch不管名称如何,都会立即执行请求,因此它的调用需要推迟到报头可用为止。它可以在安装函数之后异步调用,这是它的实现所允许的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72472766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档