Javascript 带承诺的流类型(获取和#x27;s)

Javascript 带承诺的流类型(获取和#x27;s),javascript,flowtype,Javascript,Flowtype,我创建了一个Fetch函数来使用JSON API,并为JSON对象定义了类型。我对如何定义getCurrentJobAPI函数的返回类型感到困惑,因为之后我做了大量.then()。返回值是最后一个。然后()?在我的代码中,last.then()是一个setState,那么它的类型是什么呢 getCurrentJobAPI = (): {} => { const url: string = `dummy_url&job_id=${this.props.cur

我创建了一个Fetch函数来使用JSON API,并为JSON对象定义了类型。我对如何定义
getCurrentJobAPI
函数的返回类型感到困惑,因为之后我做了大量
.then()
。返回值是最后一个。然后()?在我的代码中,last.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
定义为
getCurrentJobAPI
的返回值(请参阅的答案和注释),但我仍然不确定如果提取解析为JSON响应,为什么我不能编写
Promise

[我已将我的.then()语句压缩到per的推荐中。]

以下是
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
}

当链接then's时,结果总是一个承诺。 调用
then
时,返回值是另一个承诺,否则链接then是不可能的。
通过在整个链中使用console.log(),您可以很容易地看到这一点。

因此,首先,作为免责声明,我是TypeScript用户,但我发现这个问题实际上适用于两种语言,并且有相同的答案

我创建了一个Fetch函数来使用JSON API,并为JSON对象定义了类型。我对如何定义getCurrentJobAPI函数的返回类型感到困惑,因为之后我做了大量的.then()操作。返回值是最后一个。然后()?在我的代码中,last.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 });
            })
    };
TL;DR:
承诺
(见注释)。正如您所怀疑的,这实际上是承诺链中最后一个顶级
的返回类型

现在让我们再深入一点

这里是您的示例,稍微修改一下,以利用类型推断,而不是注释由接收者声明为
any
的回调参数

另外,这些回调参数注释相当于不安全的隐式强制转换,或者我们在TypeScript中称之为类型断言,它们与代码的形状有关。它们看起来像这样

所以我尽量减少这些,因为它们形成了一个微妙的陷阱

显然,这是一个
void
函数。它没有
return
语句。但是,作为一个
异步
函数,它固有地返回一个
承诺
,就像它作为显式
承诺
链编写时一样

注意:
void
是一种在Flow和TypeScript中被发现很有用的结构,用于表示函数的语义意图,这些函数不返回值,但实际上这些函数返回未定义的
,因为这是JavaScript。Flow似乎无法将
未定义的
识别为一个类型,但在TypeScript下,函数同样可以被注释为返回
承诺
。毫无疑问,
承诺
更可取,因为它提供了清晰的意图


备注:我使用和Windows的流二进制文件的组合完成了这项工作。Windows上的体验真的很糟糕,希望它能有所改善。

回报价值就是整个承诺链。从技术上讲,您可以获取
getCurrentJobAPI()
的结果,然后将更多的
附加到
catch
中,并在其中键入内容。这就是你要问的吗?否则我不知道该说什么。您不能返回承诺本身以外的任何内容,否则它将不再是异步的。如果返回值是整个承诺链,我如何定义流中承诺的类型?这类案件的文件在哪里?你不能。异步不是这样工作的。如果您尝试在承诺链之后运行代码,它可能会在承诺结束之前运行。所以你不能认为它返回了一个值,因为这是同步的。对不起,我刚刚意识到我没有理解你的问题。我的回答不是对你的问题的回答,但这些问题几乎都不需要。使用
。然后
返回另一个承诺,或者作为承诺链中的最终处理程序。大多数中间
。然后
处理程序只返回
未定义的
,这样您就可以将它们折叠成第一个
。然后
。那么我该如何准确定义函数的返回类型呢?我是否定义了一个包含整个链的类型?在这种情况下,返回类型将是Promise。@AvremelKaminetzky是的,在Flow Promise中是一个类型生成类型(即,它将s a类型作为参数,并在内部生成一个类型基),因此您必须为Promise指定一个类型,例如,
Promise
用于解析为字符串的承诺。您还可以使用
Promise
让Flow了解它,并使用
Promise
防止Flow检查承诺的实际类型(不建议使用,
any
仅当您没有其他选择时才应使用)。@AvremelKaminetzky无论承诺如何解决!当然,这需要你真正理解你的承诺链——即负类型,仅仅是事物本身?如果你没有完全“得到”承诺,就很难谈论类型。您必须首先理解您的代码
getCurrentJobAPI
解析承诺链的最后一个元素返回的内容。这个东西的类型就是承诺的类型——因为它总是返回一个承诺,所以您只需找出该承诺的解析形式。@AvremelKaminetzky JSON是一种字符串格式。您要么有一个JSON
字符串(!!!)-要么有一个对象。不存在“JSON对象”这样的东西,事实上这个术语本身就是一个矛盾,就像“冰火”。可以将对象编码为JSON字符串。但是你有一根绳子。其中包含一个对象,但仅当您解码它时。
// @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>
    };
}
// @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});

    };
}