将TypeScript/JavaScript的Promise转换为RxJS。

huangapple go评论65阅读模式
英文:

typescript/javascript promise into rxjs

问题

我有一些类似下面的代码:

async someFunction(){ 
    ... 
    await apiRequest()
    ...
}

apiRequest(){
    return new Promise(resolve=>{
        this.httpClient.getAuth('/api')}.subscribe({
            next: res => {
                ...
                resolve(true)
            },
            error: error => { resolve(false) }
        })
    )
}

这段代码有点不够优雅。有没有其他方式可以在不使用Promise的情况下同步调用函数?也许可以使用rxjs吗?我只需要知道api调用已完成。

英文:

I have some code like below:

async someFunction(){ 
    ... 
    await apiRequest()
    ...
  }

apiRequest(){
    return new Promise(resolve=>{
      this.httpClient.getAuth('/api')}.subscribe({
        next: res => {
            ...
            resolve(true)
        },
        error: error => { resolve(false) }
      })
    )
  }

This code is a little bit ugly. Is there any other way to synchronize call of function without using a promise ? Maybe with usage of rxjs? I just need to know that api call finished.

答案1

得分: 3

承诺(Promises)不是 Angular 的方式,Angular 基于 RxJs 构建,因此最好坚持使用 RxJs。apiRequest 应该返回 Observable,而不是将其转换为 Promise。

apiRequest() {
  return this.httpClient.getAuth('/api').pipe(
    // 可选,只有在需要服务级错误处理时才使用
    catchError(err => { yourDealWithErrrorFunction(err); })
  );
}

然后在使用它的地方进行订阅。

someFunction() {
  apiRequest().subscribe({
    next: res => { doStuffWithRes(res); },
    error: err => { handleError(err); }
  });
}

或者我们可以使用 async 管道在组件中管理订阅。

apiData$ = this.service.apiRequest(); // 可选使用 catchError(如果需要)

在模板中:

<ng-template *ngIf="apiData$ | async as apiData">
  apiData is: {{ apiData | json }}
</ng-template>

这是最常见的 Angular 模式。不建议使用承诺(promises)和 async/await。学习 RxJs,它将使您成为更好的 Angular 开发人员。将 Observable 转换为 Promise 会剥夺其 RxJs 的强大功能。RxJs 操作符允许您构建由 Observables 组成的数据流,如组合和映射数据流。这才是正确的方式,一旦理解,您将不再回头看承诺。尽管刚开始可能有点困难,但一旦掌握,就不会再考虑使用承诺。

英文:

Promises are not the Angular way, Angular is built upon RxJs so it is best to stick to RxJs. apiRequest should return the observable rather than convert it to a promise.

apiRequest() {
  return this.httpClient.getAuth(&#39;/api&#39;).pipe(
    // optional, only if you want service level error handling
    catchError(err =&gt; { yourDealWithErrrorFunction(err); })
  );
}

then you subscribe where you use it.

someFunction() {
  apiRequest().subscribe({
    next: res =&gt; { doStuffWithRes(res); },
    error: err =&gt; { handleError(err); }
  });
}

or we use the async pipe to manage subscriptions in components

apiData$ = this.service.apiRequest(); // optionally use a catchError if you want

and in the template

&lt;ng-template *ngIf=&quot;apiData$ | async as apiData&quot;&gt;
  apiData is: {{ apiData | json }}
&lt;/ng-template&gt;

This is the most common Angular pattern. Using promises and async/awaits are not recommended. Learn RxJs, it will make you a better Angular dev. Converting an observable to a promise strips it of it's RxJs superpowers. RxJs operators allow you to construct streams out of observables like combining and mapping streams. This is the way, you wont look back at promises once it clicks even though it is a bit overwhelming at first.

答案2

得分: 2

有很多方法。我认为其中一个最简单的方法是使用RxJS中的toPromise。但是,自从版本7以后,这个函数仍然是不推荐使用的。新的函数是lastValueFrom。使用方法如下:

async someFunction(){ 
    ... 
  try {
    await data = lastValueFrom(apiRequest())
    console.log(data);
  } catch (err) {
    console.log("ERROR");
  }
    ...
}

apiRequest(){
    return this.httpClient.getAuth('/api');
  }

现在你可以等待"someFunction()",像这样:

async loadAllFunction() {
  await someFunction();
  // 所有内容加载完毕... 然后做你想做的事情。
}
英文:

There are many ways. One of the simplest I think is to use toPromise from RxJS. But this function is still deprecated since version 7. The new function is lastValueFrom. Works like this:

async someFunction(){ 
    ... 
  try {
    await data = lastValueFrom(apiRequest())
    console.log(data);
  } catch (err) {
    console.log(&quot;ERROR&quot;);
  }
    ...
}

apiRequest(){
    return this.httpClient.getAuth(&#39;/api&#39;);
  }

What you can now do is wait for the "someFunction()" like:

async loadAllFunction() {
  await someFunction();
  // All loaded... do what you want.
}

答案3

得分: 1

  • async / await 使用 Promises(一个未来的值)。

  • RxJS 使用 Observables,您可以订阅多个值。

    • RxJS 还使用 .pipe() / .switchMap() 来管理多个未来的值。

我猜您正在寻找的是这两个方法,它们可以从 Observable 中获取一个 Promise。

import { firstValueFrom, lastValueFrom } from 'rxjs';
英文:
  • async / await uses promises (one future value)

  • rxjs uses observables where you subscribe to multiple values

    • rxjs also uses .pipe() / .switchMap() to manage multiple future values

I guess what you are looking for is these two methods, which gives you a promise from an observable.

import { firstValueFrom, lastValueFrom } from &#39;rxjs&#39;;


</details>



# 答案4
**得分**: -1

rxJS有一个名为`from`的运算符,用于实现这一功能 - https://www.learnrxjs.io/learn-rxjs/operators/creation/from

<details>
<summary>英文:</summary>

rxJS has a `from` operator for this - https://www.learnrxjs.io/learn-rxjs/operators/creation/from

</details>



huangapple
  • 本文由 发表于 2023年3月4日 00:13:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75629455.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定