Avr*_*zky 4 javascript flowtype
我创建了一个 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 });
})
};
Run Code Online (Sandbox Code Playgroud)
更新:
虽然我知道我应该定义为(参见GiladPromise<type>的答案和评论)的返回值,但我仍然不确定为什么如果 Fetch 解析为 JSON 响应我就无法编写。getCurrentJobAPIPromise<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
}
Run Code Online (Sandbox Code Playgroud)
首先,免责声明,我是 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;
Run Code Online (Sandbox Code Playgroud)
所以我尽量减少这些,因为它们形成了一个微妙的陷阱
// @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>
};
}
Run Code Online (Sandbox Code Playgroud)
因此,我对上面每个调用中的承诺做出断言then,但这些断言都是通过类型推断进行验证的,除了响应值上的初始类型转换之外。
getCurrentJobAPI作为进一步的证据,如果我们从的属性中删除类型声明A,flow 将推断它的类型实际上是Promise<void>。
奖励:用async/简化await。我在上面使用了几个 ESNext 功能来缩短代码并使其更令人愉快,但我们可以利用特定功能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});
};
}
Run Code Online (Sandbox Code Playgroud)
显然,这是一个void函数。它没有任何return声明。但是,作为一个async函数,它本质上返回 a Promise,就像编写为显式链时一样Promise。
注意: void是一种在 Flow 和 TypeScript 中非常有用的构造,可以表示不返回值的函数的语义意图,但实际上此类函数实际上会返回undefined,因为这是 JavaScript。Flow 似乎无法识别undefined为类型,但在 TypeScript 下,该函数同样可以注释为 returns Promise<undefined>。无论如何,Promise<void>由于它提供了明确的意图,因此更可取。
备注:我使用https://flow.org/try和适用于 Windows 的流二进制文件的组合来完成此操作。Windows 上的体验真的很糟糕,希望能有所改善。
| 归档时间: |
|
| 查看次数: |
3844 次 |
| 最近记录: |