typescript - 如何在 TypeScript 中使用 fetch

标签 typescript promise fetch-api

我正在使用 window.fetch在 Typescript 中,但我无法将响应直接转换为我的自定义类型:

我通过将 Promise 结果转换为中间“任何”变量来解决这个问题。

执行此操作的正确方法是什么?

import { Actor } from './models/actor';

fetch(`http://swapi.co/api/people/1/`)
      .then(res => res.json())
      .then(res => {
          // this is not allowed
          // let a:Actor = <Actor>res;

          // I use an intermediate variable a to get around this...
          let a:any = res; 
          let b:Actor = <Actor>a;
      })

最佳答案

下面是几个示例,从基本到在请求和/或错误处理之后添加转换:

基本:

// Implementation code where T is the returned data shape
function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText)
      }
      return response.json<T>()
    })

}

// Consumer
api<{ title: string; message: string }>('v1/posts/1')
  .then(({ title, message }) => {
    console.log(title, message)
  })
  .catch(error => {
    /* show error message */
  })

数据转换:

通常您可能需要在将数据传递给消费者之前对其进行一些调整,例如,展开顶级数据属性。这是直截了当的:

function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText)
      }
      return response.json<{ data: T }>()
    })
    .then(data => { /* <-- data inferred as { data: T }*/
      return data.data
    })
}

// Consumer - consumer remains the same
api<{ title: string; message: string }>('v1/posts/1')
  .then(({ title, message }) => {
    console.log(title, message)
  })
  .catch(error => {
    /* show error message */
  })

错误处理:

我认为你不应该直接在这个服务中直接捕获错误,而应该让它冒泡,但如果你需要,你可以执行以下操作:

function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText)
      }
      return response.json<{ data: T }>()
    })
    .then(data => {
      return data.data
    })
    .catch((error: Error) => {
      externalErrorLogging.error(error) /* <-- made up logging service */
      throw error /* <-- rethrow the error so consumer can still catch it */
    })
}

// Consumer - consumer remains the same
api<{ title: string; message: string }>('v1/posts/1')
  .then(({ title, message }) => {
    console.log(title, message)
  })
  .catch(error => {
    /* show error message */
  })

编辑

自从前一段时间写下这个答案以来,已经有了一些变化。如评论中所述,response.json<T>不再有效。不确定,找不到它被删除的位置。

对于以后的版本,您可以:

// Standard variation
function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText)
      }
      return response.json() as Promise<T>
    })
}


// For the "unwrapping" variation

function api<T>(url: string): Promise<T> {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(response.statusText)
      }
      return response.json() as Promise<{ data: T }>
    })
    .then(data => {
        return data.data
    })
}

关于typescript - 如何在 TypeScript 中使用 fetch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41103360/

相关文章:

javascript - 类型 'string | null' 不可分配给类型 'string' 。类型 'null' 不可分配给类型 'string'

javascript - 等待函数按顺序完成 Javascript

javascript - 在 Node JS Express 中使用 Promise

javascript - 具有异步功能的 promise 不等待履行

javascript - 如何将 Angular 5 应用程序嵌入到另一个页面的 HTML 中?

angular - 在构造函数或 ngOnInit 中加载异步函数

typescript - Visual Studio Code : official TypeScript extension?

arraylist - 如何创建数组列表类并在Flutter中获取数据

javascript - 在另一个函数中使用函数回调

Javascript - Vue js 从文件中获取