在 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&lt;boolean&gt;,并且应该在调用代码中进行相应的处理(通过then,也可以通过@987654327 @)。 @Cerberus 我同意你的观点,async/await 的回归是一个承诺 感谢您的回复,解决了我的问题!!并感谢@Cerberus 指出异步返回了一个承诺。 承诺不是价值!为什么这是公认的答案? @iGanja 因为async 函数返回承诺?【参考方案2】:

当我刚开始使用 Google 地图应用学习 Observables/Reactive 编程时,我遇到了这个常见问题:D!

当你发现异步函数同步返回b(默认为true)时,你意识到异步函数还没有改变b布尔标志;

要解决此问题,重组函数以将 Observable 返回给调用者可能会更容易。

也许可以查找Observablechaining 或类似概念Promisechaining。

老例子:

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`;
  

如果您可以重命名变量以使其更清晰,那就更好了。 bisDataValid。 使用 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 中使用异步函数返回值的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 异步代码类型技巧

Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )

Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )

在异步函数内部,从回调函数返回值返回 Promise(undefined) [重复]

在异步函数内部,从回调函数返回值返回 Promise(undefined) [重复]

Nodejs中异步函数的返回值