乐闻世界logo
搜索文章和话题

How to convert Promise to Observable

9 个月前提问
5 个月前修改
浏览次数102

6个答案

1
2
3
4
5
6

在RxJS中,将Promise转化为Observable是一个非常常见的操作,可以使用RxJS提供的工具函数来完成。具体来说,你可以使用from这个函数来实现这一转换。from函数可以将数组、类数组对象、Promise、迭代器等转化为Observable。

下面是一个将Promise转化为Observable的具体例子:

javascript
import { from } from 'rxjs'; // 假设我们有一个返回Promise的函数 function fetchData() { return new Promise(resolve => { setTimeout(() => { resolve('Data loaded'); }, 1000); }); } // 使用 from 将 Promise 转化为 Observable const dataObservable = from(fetchData()); // 订阅 Observable 来处理数据 dataObservable.subscribe({ next(data) { console.log(data); // 输出:Data loaded }, error(err) { console.error('Something wrong occurred: ' + err); }, complete() { console.log('Done'); } });

在上面的代码中,fetchData函数返回一个将在1秒后解析的Promise。我们通过from函数把这个Promise转换成Observable,然后通过subscribe方法订阅这个Observable,以便当Promise解析后,我们可以接收到数据并进行处理。

使用from函数来转换Promise到Observable的方法非常简单且强大,因为它让Promise可以无缝地融入到RxJS的响应式编程模式中,使得对异步操作的处理更加灵活和强大。

2024年6月29日 12:07 回复

如果您使用的是 RxJS 6.0.0:

shell
import { from } from 'rxjs'; const observable = from(promise);
2024年6月29日 12:07 回复

1 直接执行/转换

用于from直接将先前创建的 Promise 转换为 Observable。

shell
import { from } from 'rxjs'; // getPromise() is called once, the promise is passed to the Observable const observable$ = from(getPromise());

observable$将成为一个热门的 Observable,它可以有效地向订阅者重放 Promise 值。

它是一个热门的 Observable,因为生产者(在本例中为 Promise)是在 Observable 外部创建的。多个订阅者将共享同一个 Promise。如果内部 Promise 已得到解决,Observable 的新订阅者将立即获得其值。

2 每个订阅的延迟执行

使用deferPromise 工厂函数作为输入,以推迟 Promise 到 Observable 的创建和转换。

shell
import { defer } from 'rxjs'; // getPromise() is called every time someone subscribes to the observable$ const observable$ = defer(() => getPromise());

observable$将是一个冷的 Observable

它是一个冷的 Observable,因为生产者(Promise)是在 Observable 内部创建的。每个订阅者将通过调用给定的 Promise 工厂函数来创建一个新的 Promise。

这允许您创建一个 Promise observable$,而无需立即创建并执行 Promise,也无需与多个订阅者共享此 Promise。每个用户都可以observable$有效地进行呼叫from(promiseFactory()).subscribe(subscriber)。因此,每个订阅者创建自己的新 Promise 并将其转换为新的 Observable,并将自己附加到这个新的 Observable。

3 不少运营商直接接受承诺

大多数组合(例如,,,merge... concat)或转换可观察值(例如,,,, ...)的RxJS 运算符直接接受 Promise forkJoin。如果您无论如何都使用其中之一,则不必首先使用包装承诺(但要创建**冷可观察,**您仍然可能需要使用)。combineLatest``switchMap``mergeMap``concatMap``catchError``from``defer

shell
// Execute two promises simultaneously forkJoin(getPromise(1), getPromise(2)).pipe( switchMap(([v1, v2]) => v1.getPromise(v2)) // map to nested Promise )

检查文档实施以查看您使用的运算符是否接受ObservableInputSubscribableOrPromise

shell
type ObservableInput<T> = SubscribableOrPromise<T> | ArrayLike<T> | Iterable<T>; // Note the PromiseLike ----------------------------------------------------v type SubscribableOrPromise<T> = Subscribable<T> | Subscribable<never> | PromiseLike<T> | InteropObservable<T>;

from和之间的区别defer示例: https://stackblitz.com/edit/rxjs-6rb7vf

shell
const getPromise = val => new Promise(resolve => { console.log('Promise created for', val); setTimeout(() => resolve(`Promise Resolved: ${val}`), 5000); }); // the execution of getPromise('FROM') starts here, when you create the promise inside from const fromPromise$ = from(getPromise('FROM')); const deferPromise$ = defer(() => getPromise('DEFER')); fromPromise$.subscribe(console.log); // the execution of getPromise('DEFER') starts here, when you subscribe to deferPromise$ deferPromise$.subscribe(console.log);

defer可能是大多数人正在寻找的运算符,因为许多应用程序都依赖 Observables 来保持冷状态并在订阅时触发数据获取。from不过,对于某些用例来说,这仍然是一个可行的选择,例如,当您想在某些初始化过程中创建一次 Promise,然后通过将被订阅多次的 Observable 传播其值,但又不想创建和执行再次向每一位订阅者承诺。

2024年6月29日 12:07 回复

尝试这个:

shell
import 'rxjs/add/observable/fromPromise'; import { Observable } from "rxjs/Observable"; const subscription = Observable.fromPromise( firebase.auth().createUserWithEmailAndPassword(email, password) ); subscription.subscribe(firebaseUser => /* Do anything with data received */, error => /* Handle error here */);

您可以在此处找到 fromPromise 运算符的完整参考。

2024年6月29日 12:07 回复

将 Promise 转换为 Observable 的正确**模式****defer是使用andfrom**运算符:

shell
import { defer, from } from 'rxjs'; const observable$ = defer(() => from(myPromise()));

为什么我们需要defer运营商?

Promise 是急切的,这意味着当被调用时它们会立即触发。这与可观察量的工作方式相反。Observables 是惰性的,它们仅在.subscribe()被调用时才会被触发。这就是我们需要始终将其包装到运算符中的原因defer。操作from员不做这项工作,所以defer总是需要

2024年6月29日 12:07 回复

您可以添加一个围绕 Promise 功能的包装器,以将 Observable 返回给观察者。

  • 使用defer()运算符创建Lazy Observable ,它允许您仅在观察者订阅时创建 Observable。

    import { of, Observable, defer } from 'rxjs'; import { map } from 'rxjs/operators';

    function getTodos$(): Observable { return defer(()=>{ return fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => { return json; }) }); }

    getTodos$(). subscribe( (next)=>{ console.log('Data is:', next); } )

2024年6月29日 12:07 回复

你的答案