在 Typescript 中使用异步函数返回值
Posted
技术标签:
【中文标题】在 Typescript 中使用异步函数返回值【英文标题】:Return value with asynchronous functions in Typescript 【发布时间】:2018-12-12 11:12:45 【问题描述】:我有以下TS功能:
CheckRegUser(u: User): boolean
let b: boolean = true;
let toSend =
email: u.email
;
this.http.post("http://localhost:8080/", toSend).subscribe((data: Valid) =>
if(!data.validity)
b = false;
);
console.log(b);
return b;
这里我连接到 ExpressJS 后端,我得到一个布尔结果。这部分工作正常,但问题是在“this.http”中改变b的值之前执行了“return b”语句,所以无论Express的响应是什么,b总是正确的。
我知道 TS 和 JS 是异步的,因此导致了这个问题,但是我找不到解决问题的正确方法。任何帮助,将不胜感激。
【问题讨论】:
可能重复***.com/questions/34210812/… 【参考方案1】:你可以试试async await
async CheckRegUser(u: User): Promise<boolean>
let toSend =
email: u.email
;
let k = await this.http.post("http://localhost:8080/", toSend).subscribe((data: Valid)
let b: boolean = true;
if(!data.validity)
b = false;
return b
);
console.log(k);
return k;
【讨论】:
请注意,这意味着CheckRegUser
将返回的不是boolean
,而是Promise<boolean>
,并且应该在调用代码中进行相应的处理(通过then
,也可以通过@987654327 @)。
@Cerberus 我同意你的观点,async/await
的回归是一个承诺
感谢您的回复,解决了我的问题!!并感谢@Cerberus 指出异步返回了一个承诺。
承诺不是价值!为什么这是公认的答案?
@iGanja 因为async
函数返回承诺?【参考方案2】:
当我刚开始使用 Google 地图应用学习 Observables/Reactive 编程时,我遇到了这个常见问题:D!
当你发现异步函数同步返回b
(默认为true
)时,你意识到异步函数还没有改变b
布尔标志;
要解决此问题,重组函数以将 Observable
返回给调用者可能会更容易。
也许可以查找Observable
chaining 或类似概念Promise
chaining。
老例子:
CheckRegUser(u: User): boolean
const b: boolean = true;
const toSend =
email: u.email
;
const httpPost: Observable<aJsonObject> = this.http.post("http://localhost:8080/", toSend)
const httpPostSubscription: Subscription = httpPost
.subscribe((data: Valid) => // This is asynchronous
if (!data.validity)
b = false;
);
console.log(b);
return b; // This is effectively sync returning your default value `b = true`;
如果您可以重命名变量以使其更清晰,那就更好了。
b
或 isDataValid
。
使用 const
变量开始函数式风格也可能是一种很好的做法,以帮助避免可变性问题。
如果你更熟悉Promises
,你也可以尝试promisify
httpClient.post Observable。
它的一般要点是将Observable
传回给调用者并在那里传递.subscribe
。
当某些东西异步返回时,您应该将异步性一直返回到顶部。
重构代码以反映这些做法
CheckRegUser(user: User, httpClient: HttpClient): Observable<Valid>
// 1. Data to send
type EmailPost = email: string
const emailJsonToSend: EmailPost = // I prefer explicit typing wherever possible :tada: :D
email: user.email
;
// 2. POST the data to the web server
const emailHttpPostObs: Observable<Valid> = httpClient.post("http://localhost:8080/", emailJsonToSend);
return emailHttpPostObs;
CallerSubmitUserFunction(user: User, httpClient: HttpClient)
// Made some assumptions, please comment and we can work out a better solution
// Explicitly typed things as an example.
// 1. You have a user e.g. new User(name:'myUser', email: 'myEmailAddressOrEmailContent@email.com');
const userToSend: User = user;
// 2. You POST the user.email and get response.
const validatedUserDataObs: Observable<Valid> = CheckRegUser(userToSend, httpClient);
// 3. You check whether the server accepted the data and whether it was valid.
const validatedUserDataObs: Subscription = validatedUserDataObs
.subscribe((data: Valid) =>
// Perform data validation or Error checking here.
// If data is valid,
if (dataValidationFunction())
// Do something here
// Instead of trying to return the boolean in the asynchronouse function.
// Directly do something after the server responds (whenever it happens).
) // catch Error
// It would also be better if you could rename your variables to be more self-indicative
// var dataIsValid
【讨论】:
感谢您非常详细的回答,它确实解释得很好,但我更愿意为我的问题提供一个简单明了的解决方案。但是,再次感谢您为编写此答案所付出的努力!以上是关于在 Typescript 中使用异步函数返回值的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )
Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )
在异步函数内部,从回调函数返回值返回 Promise(undefined) [重复]