2017-10-17 108 views
2

我想将promise链重构为async/await,但Typescript正在抱怨打字。为什么Typescript认为async/await返回承诺中包含的值?

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); 
} 

如果我从常量RESP声明中删除 “IResp”,processResponse抱怨IHttp < IResp>不等于IResp ...

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

请提供一个最小的完整示例。 – NineBerry

+3

IHttpPromiseCallbackArg类型不是承诺。这已经是函数调用的实际结果。请参阅http://definitelytyped.org/docs/angular-translate--angular-translate/interfaces/ng.ihttppromisecallbackarg.html – NineBerry

+0

我可以将我的问题改写为 - “我认为await会返回与第一个参数相同的值在'.then'回调中,我错了吗?“ – user2954463

回答

3

您的问题“我以为等待会返回与.then回调中的第一个参数相同的值,我错了吗?”。

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

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

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

所以,一个IHttpPromise<T>是返回IHttpPromiseCallbackArg<T>放回原处T类型的实际数据是IHttpPromiseCallbackArg<T>data财产的承诺。

因此,旧代码变种,我们在这个问题看:

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

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

实际上应该不无打字稿错误时myAsyncRequest定义为返回IHttpPromise编译。

HOWTO修复此:

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>

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

myAsyncRequest(params:IParams):IHttpPromise<Something> { 
-2

包含await确实伺机解决线值 - 但是因为函数本身是异步的(允许所有等待的),你会得到一个承诺。

例......在下面的代码,你可以为y使用x作为一个普通的数字(尽管delay回报承诺),并再次 - 所以你等待的东西解决了,所以你可以像你会用这如果它是同步的。

看起来不像它返回承诺的异步函数现在可以实现。

这看起来很让人困惑,因为它似乎“反转了承诺”,但它所做的是将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)); 
+0

因此,在一天结束时,我仍然需要在某处调用'.then'? – user2954463

+0

你可能还需要在最上面调用'then'(在某些情况下,你将函数传递给别的东西的时候,你不需要)。 – Fenton

+1

什么是downvote?任何改善答案的建议? –