typescript async函数必需返回promise么
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了typescript async函数必需返回promise么相关的知识,希望对你有一定的参考价值。
1.promisepromise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。(其中rejectedHandler可选)。
以下为一个有几级嵌套的函数,看起来比较令人恶心。(如果换成缩进四个字符可想而知)
\'use strict\'; const md = require(\'markdown-it\')(); const fs = require(\'fs\'); fs.watchFile(\'nodejs.md\', (curr, prev) => let mdStr = fs.readFile(\'./nodejs.md\', \'utf-8\', (err, data) => let mdData = md.render(data); let htmlTemplate = fs.readFile(\'./index.html\', \'utf-8\', (err, data) => let html = data.replace(\'content\', mdData); console.log(mdData); fs.writeFile(\'./nodejs.html\', html, \'utf-8\', (err, data) => if (err) throw err; else console.log(\'OK\'); ); ); ); );
一下用promise的方式实现同样的效果,首先把异步函数封装一下,然后下面可以指教调用。可能看起来代码比之前的版本更多,但是封装的异步函数是可以复用的。等任务多了就不显得代码多了。(但看最后调用函数的部分是不是优雅了不少) 参考技术A 确实需要返回Promise对象,但是这里的返回指的是函数返回类型,而函数内部的return 可以是其他类型。例如async fn(): Promise<string> return '111'
为啥 Typescript 认为 async/await 返回包装在承诺中的值?
【中文标题】为啥 Typescript 认为 async/await 返回包装在承诺中的值?【英文标题】:Why does Typescript think async/await returns a value wrapped in a promise?为什么 Typescript 认为 async/await 返回包装在承诺中的值? 【发布时间】:2018-03-29 15:07:14 【问题描述】:我想将一个 Promise 链重构为 async/await,但 Typescript 抱怨打字。
TS2322:类型“IHttpPromiseCallbackArg”不可分配给类型“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);
如果我从 const resp 声明中删除“IResp”,则 processResponse 会抱怨 IHttp
processResp(resp:IResp)
//do stuff
【问题讨论】:
IHttpPromiseCallbackArg 类型不是承诺。这已经是函数调用的实际结果了。见definitelytyped.org/docs/angular-translate--angular-translate/… 我可以将我的问题改写为 - “我认为await
会返回与 .then
回调中的第一个参数相同的值。我错了吗?”
你是对的。但是你对 then 回调函数中第一个参数的类型是错误的。见definitelytyped.org/docs/angularjs--angular-route/interfaces/…
也许您对实际使用的类型定义错误。但是我们需要一个完整的工作示例来明确地说明这一点。
【参考方案1】:
包含await
的行确实等待解析的值 - 但由于函数本身是异步的(允许所有等待),你会得到一个承诺。
示例...在下面的代码中,您可以将x
用作纯数字(即使delay
返回一个承诺)并再次用于y
- 因此您等待的所有内容都已解决,因此您可以使用如果它是同步的,它更像你会的。
看起来不像它的异步函数返回了一个承诺,现在可以了。
这似乎令人困惑,因为它似乎“颠倒了承诺”,但它所做的是将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));
【讨论】:
所以说到底,我还是得在某个地方打电话给.then
?
您可能仍然必须在最顶部调用then
(在某些情况下,您将函数传递给其他东西,您不必这样做) .
反对票是怎么回事?有什么改进答案的建议吗?
这并没有回答似乎对函数返回的类型有误解的问题。 IHttpPromiseCallbackArg 类型不是提问者所假设的承诺。
我试图回答“我认为 await 会返回一个常规值,而不是一个承诺。我错了吗?”【参考方案2】:
您的问题“我认为 await 会返回与 .then 回调中的第一个参数相同的值。我错了吗?”。
不,你完全正确。但是您对 .then 回调中的第一个参数是错误的。
您将myAsyncRequest
定义为返回IHttpPromise<IResp>
。但是IHttpPromise<T>
被定义为继承IPromise
,方式如下:
type IHttpPromise<T> = IPromise<IHttpPromiseCallbackArg<T>>;
因此,IHttpPromise<T>
是一个返回 IHttpPromiseCallbackArg<T>
的承诺,其中 T
类型的实际数据位于 data
的 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
被定义为返回 IHttpPromise
时,实际上不应该在 TypeScript 中正确编译。
如何解决这个问题:
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);
注意:在最新的 Angular 类型定义中,IHttpPromiseCallbackArg<T>
类型实际上称为IHttpResponse<T>
。
也许在您的代码中,您已将IResp
定义为IHttpResponse<Something>
?那么你只是与旧名称IHttpPromiseCallbackArg
发生冲突。然后从DefinitelyTyped 获取使用新名称的最新类型定义。您还必须将myAsyncRequest
的定义更改为:
myAsyncRequest(params:IParams):IHttpPromise<Something>
【讨论】:
以上是关于typescript async函数必需返回promise么的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript:用于在 setTimeout() 中返回异步函数调用的类型?
Typescript async/await 无法确定正确的返回类型