vue.js 如何正确 Package `useFetch`以访问React性?

vecaoik1  于 2023-11-21  发布在  Vue.js
关注(0)|答案(1)|浏览(156)

我将useFetch() Package 为一个composable来提供一个自定义的baseURL并自动设置一个身份验证令牌,但是当我在一个没有await关键字的组件中调用这个composable时,它的行为并不像预期的那样具有React性。通常,我可以调用const { data, pending, status } = useFetch('...'),一旦promise解析并且data可用,UI就会更新。但是对于 Package 器,这不起作用。似乎我必须始终使用awaituseCustomFetch()
知道为什么这行不通吗
下面是自定义 Package 。

import type { UseFetchOptions } from 'nuxt/app'
import { defu } from 'defu'

export async function useCustomFetch<T>(url: string, options: UseFetchOptions<T> = {}) {
  const config = useRuntimeConfig()
  const { data, status, getSession }: { data: any; status: any; getSession: Function } = useAuth()

  const headers: HeadersInit | undefined = {}

  // NOTE: Set 'Authorization' header
  if (data && status.value === 'authenticated') {
    const session = await getSession({ required: true })
    headers.Authorization = `Bearer ${session.accessToken}`
  }

  const defaults: UseFetchOptions<T> = {
    baseURL: config.public.baseApiUrl,
    headers,
    onResponse(_ctx) {
      // EX: _ctx.response._data = new myBusinessResponse(_ctx.response._data)
    },
    onResponseError(_ctx) {
      // TODO: Send notification to Sentry
    },
  }

  // NOTE: Deep defaults, use unjs/defu
  const params = defu(options, defaults)

  return useFetch(url, params)
}

字符串
在一个组件中,这不 * 工作。

<script setup>
const { data, pending, status } = useCustomFetch('/resources')
</script>

gcmastyq

gcmastyq1#

useAsyncData和其他依赖于它的组合(在本例中为useFetch)返回增强的promise。async函数总是返回不影响其工作方式的原生promise,但没有来自增强promise的data等。为了保留原始行为,useCustomFetch应该使用原始promise并实现增强。

function useCustomFetch<T>(url: string, options: UseFetchOptions<T> = {}) {
  let promise = Promise.resolve<unknown>(null);

  if (data && status.value === 'authenticated') {
    promise = promise
      .then(() => getSession({ required: true }))
      .then(session => {
        headers.Authorization = `Bearer ${session.accessToken}`
      })
  }

  ...

  promise = promise
    .then(() => useFetch(url, params));
  Object.assign(promise, ???);

  return promise as ReturnType<(typeof useFetch)<T>;
}

字符串
可以看出,这种方法会产生一个问题,因为当立即返回结果时,不存在要增加的属性。这将需要通过创建新的data来增加另一个复杂性级别,等引用并将它们的结果同步到useFetch。正是await getSession使实现变得不必要的复杂,并且当可组合对象不使用await
getSession调用应该被移动到fetch选项,然后这变得很简单,这允许推断结果的类型,并可能导致更正确的行为,因为请求在重新获取时不会使用旧的session

function useCustomFetch<T>(url: string, options: UseFetchOptions<T> = {}) {
  ...
 const defaults: UseFetchOptions<T> = {
   async onRequest(_ctx) {
     const session = await getSession({ required: true })
     _ctx.options.headers = {
       ..._ctx.options.headers,
       Authorization: `Bearer ${session.accessToken}`
     }
   },
  ...
  return useFetch(url, params);
}


请注意,文档中没有列出增广的promise和不带await的用法。由于这没有文档记录,因此不应依赖于此,并且可以在不通知的情况下更改。
如果请求应该被延迟执行而不等待结果,那么useFetch和自定义组合可以与lazy选项一起使用:

await useCustomFetch(url, { lazy: true, ... })

相关问题