AbortSignal在TanStack的useQuery函数中何种情况下是未定义的?

huangapple go评论91阅读模式
英文:

Under which conditions is the AbortSignal in the TanStack useQuery function undefined?

问题

TanStack React Query文档(https://tanstack.com/query/v4/docs/react/guides/query-cancellation)解释了queryFn属性如何接收一个带有signal属性的对象,该属性可用于取消查询,就像这个示例中一样。

const query = useQuery({
  queryKey: ['todos'],
  queryFn: async ({ signal }) => {
    const todosResponse = await fetch('/todos', {
      signal,
    })
    const todos = await todosResponse.json()
    const todoDetails = todos.map(async ({ details }) => {
      const response = await fetch(details, {
        signal,
      })
      return response.json()
    })

    return Promise.all(todoDetails)
  },
})

问题是,使用TypeScript时,这个signal属性的类型是AbortSignal | undefined。根据我正在使用的API,不得不条件性地检查signal是否已设置会给代码增加很多复杂性,因此知道在哪些情况下signal对象未定义将非常有帮助。有任何想法将不胜感激。

英文:

The documentation of TanStack React Query (https://tanstack.com/query/v4/docs/react/guides/query-cancellation) explains how the queryFn property can receive an object with a signal property, which can be used to cancel a query, like in this example.

const query = useQuery({
  queryKey: ['todos'],
  queryFn: async ({ signal }) => {
    const todosResponse = await fetch('/todos', {
      signal,
    })
    const todos = await todosResponse.json()
    const todoDetails = todos.map(async ({ details }) => {
      const response = await fetch(details, {
        signal,
      })
      return response.json()
    })

    return Promise.all(todoDetails)
  },
})

The problem is that, with TypeScript, this signal property is type as AbortSignal | undefined. With the API that I am using, having to conditionally check if the signal is set adds a lot of complexity to the code so it would be very helpful to know under which conditions this signal object is not defined. Any ideas would be much appreciated.

答案1

得分: 1

react-query v4.29.11

如果AbortController类存在,则会存在signal。让我们看一下源代码:

signal属性是通过addSignalProperty()函数添加到查询函数上下文中的,如下所示:

const addSignalProperty = (object: unknown) => {
  Object.defineProperty(object, 'signal', {
    enumerable: true,
    get: () => {
      if (abortController) {
        this.abortSignalConsumed = true
        return abortController.signal
      }
      return undefined
    },
  })
}

addSignalProperty(queryFnContext)

通过getAbortController()函数获取abortController

export function getAbortController(): AbortController | undefined {
  if (typeof AbortController === 'function') {
    return new AbortController()
  }
  return
}

这就是为什么signal属性的TS类型是:AbortSignal | undefined

官方文档也提到了这一点。

AbortController API 在大多数运行时环境中都可用,但如果运行时环境不支持它,那么查询函数将接收到undefined。如果愿意,您可以选择使用几种可用的方法来进行AbortController API 的polyfill。

英文:

react-query v4.29.11

The signal will exist if the AbortController class exists. Let's take a look at the source code:

The signal property is added to the query function context by addSignalProperty() function, see below:

    const addSignalProperty = (object: unknown) => {
      Object.defineProperty(object, 'signal', {
        enumerable: true,
        get: () => {
          if (abortController) {
            this.abortSignalConsumed = true
            return abortController.signal
          }
          return undefined
        },
      })
    }

    addSignalProperty(queryFnContext)

The abortController is got by getAbortController() function

export function getAbortController(): AbortController | undefined {
  if (typeof AbortController === 'function') {
    return new AbortController()
  }
  return
}

That's why the TS type of signal property is: AbortSignal | undefined.

The official documentation also mentions it.

> The AbortController API is available in most runtime environments, but if the runtime environment does not support it then the query function will receive undefined in its place. You may choose to polyfill the AbortController API if you wish, there are several available.

huangapple
  • 本文由 发表于 2023年5月29日 18:02:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定