我创建了一个Fetch函数来使用JSON API并为JSON对象定义了类型。我对如何定义getCurrentJobAPI
函数的返回类型感到困惑,因为之后我做了一堆.then()
。返回值是最后一个.then()吗?在我的代码中,最后一个.then()是一个setState,那么该类型是什么?
getCurrentJobAPI = (): {} => {
const url: string = `dummy_url&job_id=${this.props.currentJob}`;
return fetch(url, {credentials: 'include'})
.then((response) => {
return response.json();
})
.then((json: CurrentJob) => {
console.log(json);
const location = json.inventoryJob.location;
const ref_note = json.inventoryJob.note;
const id = json.inventoryJob.id;
const models = json.inventoryJobDetails.map((j) => {
return Object.assign({}, {
code: j.code,
qty: j.qty
})
});
this.setState({ currentCodes: models, location: location, ref_note: ref_note, id: id})
return json
})
.then((json: CurrentJob) => {
const barcodes = json.inventoryJob.history;
if (barcodes.length > 0) {
this.setState({apiBarcodes: barcodes})
}
this.calculateRows();
this.insertApiBarcodes();
this.setState({ initialLoad: true });
})
};
更新:
虽然我理解我应该将Promise<type>
定义为getCurrentJobAPI
的返回值(请参阅Gilad的答案和评论),但我仍然不确定为什么我如果Fetch解析为JSON响应,则无法写Promise<CurrentJob>
。
[我根据loganfsmyth的重新推荐浓缩了我的.then()语句。]
以下是CurrentJob
的类型定义:
type Job = {
user_id: number,
status: 'open' | 'closed',
location: 'string',
history: {[number]: string}[],
note: string,
} & CommonCurrentJob;
type JobDetails = {
iaj_id: number,
code: number,
} & CommonCurrentJob;
type CommonCurrentJob = {
id: number,
qty: number,
qty_changed: number,
created_at: string,
updated_at: string
}
答案 0 :(得分:2)
首先,免责声明,我是TypeScript用户,但我发现这个问题实际上适用于这两种语言并且答案相同。
我创建了一个Fetch函数来使用JSON API并为JSON对象定义了类型。我很困惑如何定义getCurrentJobAPI函数的返回类型,因为之后我做了一堆.then()。返回值是最后一个.then()吗?在我的代码中,最后一个.then()是一个setState,那么该类型是什么?
TL; DR:Promise<void>
(见注释)。正如您所怀疑的那样,这实际上是承诺链中最后一个顶级.then
的返回类型。
现在让我们深入挖掘一下
以下是您的示例,稍微重写以利用类型推断,而不是注释其接收方声明为any
的回调参数。
顺便说一下,这些回调参数注释相当于不安全的隐式转换,或者在我们在TypeScript中调用它们时键入断言,它们与代码的形状有关。他们看起来像这样
declare function takesFn(fn: (args: any) => any): void;
所以我把它们最小化了,因为它们形成了一个微妙的陷阱
// @flow
import React from 'react';
type CurrentJob = {
inventoryJob: Job,
inventoryJobDetails: JobDetails[]
}
export default class A extends React.Component<{currentJob:JobDetails}, any> {
getCurrentJobAPI: () => Promise<void> = () => {
const url = `dummy_url&job_id=${String(this.props.currentJob)}`;
return fetch(url, {credentials: 'include'})
.then(response => {
return (response : {json(): any}).json();
}) // --> Promise<any>
.then(json => {
const currentJob = (json: CurrentJob); // make the assumption explicit.
console.log(currentJob);
const {location, id, note: ref_note} = currentJob.inventoryJob;
const currentCodes = currentJob.inventoryJobDetails
.map(({code, qty}) => ({
code,
qty
}));
this.setState({currentCodes, location, ref_note, id});
return currentJob;
}) // --> Promise<CurrentJob>
.then(currentJob => {
const apiBarcodes = currentJob.inventoryJob.history;
if (apiBarcodes.length > 0) {
this.setState({apiBarcodes});
}
this.setState({initialLoad: true});
}); // --> Promise<void>
};
}
所以我在上面的每个then
调用中对promise进行了断言,但这些断言都是通过类型推断验证的,除了响应值的初始类型转换。
作为进一步的证据,如果我们从getCurrentJobAPI
的{{1}}属性中删除类型声明,则流程将推断其类型实际上是A
。
额外奖励:使用Promise<void>
/ async
进行简化。我已经使用上面的几个ESNext功能来缩短代码并使其更加愉快,但我们可以利用特定功能await
/ async
来更轻松地理解控制流和基于await
的代码中的类型。
考虑这个修订版。
Promise
显然,这是一个// @flow
import React from 'react';
type CurrentJob = {
inventoryJob: Job,
inventoryJobDetails: JobDetails[]
}
export default class A extends React.Component<{currentJob:JobDetails}, any> {
getCurrentJobAPI = async () => {
const url = `dummy_url&job_id=${String(this.props.currentJob)}`;
const response = await fetch(url, {credentials: 'include'});
const json = await response.json();
const currentJob = (json: CurrentJob); // make the assumption explicit.
console.log(currentJob);
const {location, id, note: ref_note} = currentJob.inventoryJob;
const currentCodes = currentJob.inventoryJobDetails.map(({code, qty}) => ({
code,
qty
}));
this.setState({currentCodes, location, ref_note, id});
const apiBarcodes = currentJob.inventoryJob.history;
if (apiBarcodes.length > 0) {
this.setState({apiBarcodes});
}
this.setState({initialLoad: true});
};
}
函数。它没有void
个语句。但是,作为return
函数,它本身会返回async
,就像写入显式Promise
链时一样。
注意: Promise
是一个在Flow和TypeScript中有用的构造,用于表示不返回值的函数的语义意图,但实际上这些函数实际返回{{ 1}}因为,这是JavaScript。 Flow似乎不会将void
识别为类型,但在TypeScript下,该函数同样可以注释为返回undefined
。无论如何,由于其提供的意图清晰,undefined
更为可取。
备注:我使用https://flow.org/try和Windows的流二进制文件组合完成了这项工作。 Windows上的体验非常糟糕,希望它会有所改善。
答案 1 :(得分:1)
当链接时,结果将永远是一个承诺。
在致电then
时,返回值是另一个承诺,否则链接就不可能了。
您可以通过使用围绕整个链的console.log()轻松地看到它。