如何在打字稿中使用 fetch [英] How to use fetch in typescript

查看:60
本文介绍了如何在打字稿中使用 fetch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using window.fetch in Typescript, but I cannot cast the response directly to my custom type:

我通过将 Promise 结果转换为中间的任何"变量来解决这个问题.

I am hacking my way around this by casting the Promise result to an intermediate 'any' variable.

这样做的正确方法是什么?

What would be the correct method to do this?

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;
      })

推荐答案

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

A few examples follow, going from basic through to adding transformations after the request and/or error handling:

// 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 */
  })

数据转换:

通常您可能需要在数据传递给消费者之前对其进行一些调整,例如,解开顶级数据属性.这很简单:

Data transformations:

Often you may need to do some tweaks to the data before its passed to the consumer, for example, unwrapping a top level data attribute. This is straight forward:

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 */
  })

错误处理:

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

Error handling:

I'd argue that you shouldn't be directly error catching directly within this service, instead, just allowing it to bubble, but if you need to, you can do the following:

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 不再有效.不确定,找不到它被删除的地方.

Edit

There has been some changes since writing this answer a while ago. As mentioned in the comments, response.json<T> is no longer valid. Not sure, couldn't find where it was removed.

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

For later releases, you can do:

// 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
    })
}

这篇关于如何在打字稿中使用 fetch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆