typescript 如何在打字稿中使用 fetch
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41103360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use fetch in typescript
提问by Kokodoko
I am using window.fetchin Typescript, but I cannot cast the response directly to my custom type:
我在 Typescript 中使用window.fetch,但我无法将响应直接转换为我的自定义类型:
I am hacking my way around this by casting the Promise result to an intermediate 'any' variable.
我通过将 Promise 结果转换为中间的“任何”变量来解决这个问题。
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;
})
回答by Chris
A few examples follow, going from basic through to adding transformations after the request and/or error handling:
下面是一些示例,从基本到在请求和/或错误处理之后添加转换:
Basic:
基本的:
// 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 */
})
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.
自从不久前写下这个答案以来,发生了一些变化。如评论中所述,response.json<T>
不再有效。不确定,找不到它被删除的地方。
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
})
}
回答by nicowernli
If you take a look at @types/node-fetchyou will see the body definition
如果您查看@types/node-fetch,您将看到主体定义
export class Body {
bodyUsed: boolean;
body: NodeJS.ReadableStream;
json(): Promise<any>;
json<T>(): Promise<T>;
text(): Promise<string>;
buffer(): Promise<Buffer>;
}
That means that you could use generics in order to achieve what you want. I didn't test this code, but it would looks something like this:
这意味着您可以使用泛型来实现您想要的。我没有测试这段代码,但它看起来像这样:
import { Actor } from './models/actor';
fetch(`http://swapi.co/api/people/1/`)
.then(res => res.json<Actor>())
.then(res => {
let b:Actor = res;
});