为什么Typescript认为async / await返回一个包含在promise中的值?

时间:2017-10-17 20:07:15

标签: javascript angularjs typescript ecmascript-2017

我想将一个promise链重构为async / await,但是Typescript抱怨打字。

  

TS2322:输入' IHttpPromiseCallbackArg< IResp>'不能分配给' IResp' ...

我认为await会返回一个常规值,而不是一个承诺。我错了吗?如果是这样,我如何分配输入以便编译所需的代码?

我认为await将返回与.then回调中的第一个参数相同的值。我错了吗?

旧代码:

handleSubmit(form) {
    const params = this.getParams(form);

    this.myAsyncRequest(params)
       .then((resp:IResp) => this.processResp(resp))
       .catch((e:IServerError) => this.handleError(e));
 }

所需的新代码:

async handleSubmit(form) {
    const params = this.getParams(form);

    try {
        const resp:IResp = await this.myAsyncRequest(params); //typing error with "const resp:IResp"
        this.processResp(resp);
    } catch (e:IServerError) {
        this.handleError(e);
    }
}

如果删除myAsyncRequest中的返回类型,所需的代码仍会中断;我猜Typescript直接来自AngularJS库。

myAsyncRequest(params:IParams):IHttpPromise<IResp> {
    return $http.post('blah', data);
}

如果我删除&#34; IResp&#34;从const resp声明中,processResponse抱怨IHttp&lt; IResp&GT;不等于IResp ...

processResp(resp:IResp) {
    //do stuff
}

2 个答案:

答案 0 :(得分:4)

你的问题“我认为await将返回与.then回调中的第一个参数相同的值。我错了吗?”。

不,你是对的。但你对.then回调中的第一个参数是错误的。

您定义myAsyncRequest以返回IHttpPromise<IResp>。但IHttpPromise<T>被定义为以下列方式继承IPromise

type IHttpPromise<T> = IPromise<IHttpPromiseCallbackArg<T>>;

因此,IHttpPromise<T>是一个返回IHttpPromiseCallbackArg<T>的承诺,其中T类型的实际数据位于data的{​​{1}}属性中

所以,我们在问题中看到的旧代码变体:

IHttpPromiseCallbackArg<T>
handleSubmit(form) { const params = this.getParams(form); this.myAsyncRequest(params) .then((resp:IResp) => this.processResp(resp)) .catch((e:IServerError) => this.handleError(e)); } 被定义为返回myAsyncRequest时,

实际上不应该在TypeScript中编译而没有错误。

如何解决这个问题:

IHttpPromise

注意:在角度的最新类型定义中,类型async handleSubmit(form) { const params = this.getParams(form); try { const httpResp:IHttpPromiseCallbackArg<IResp> = await this.myAsyncRequest(params); const resp: IResp = httpResp.data; this.processResp(resp); } catch (e:IServerError) { this.handleError(e); } } 实际上称为IHttpPromiseCallbackArg<T>

也许在您的代码中,您已将IHttpResponse<T>定义为IResp?然后,您只是与旧名称IHttpResponse<Something>发生冲突。然后从DefinitelyTyped获取使用新名称的最新类型定义。而且您还必须将IHttpPromiseCallbackArg的定义更改为:

myAsyncRequest

答案 1 :(得分:-1)

包含await的行确实等待已解析的值 - 但由于函数本身是异步的(允许所有等待的),您将获得一个承诺。

示例...在下面的代码中,您可以使用x作为普通数字(即使delay返回承诺),也可以使用y - 所以您等待的所有内容已经解决了,所以你可以像使用同步一样使用它。

async函数似乎不会返回一个promise,现在就是。

这看起来有点令人困惑,因为它似乎反转了承诺&#34;但它的作用是将then转移到顶层(你可以让异步函数调用其他异步)功能等)。

function delay(ms: number) {
    return new Promise<number>(function(resolve) {
        setTimeout(() => {
            resolve(5);
        }, ms);
    });
}


async function asyncAwait() {
    let x = await delay(1000);
    console.log(x);

    let y = await delay(1000);
    console.log(y);

    return 'Done';
}

asyncAwait().then((result) => console.log(result));