哪个更合适——concat 还是 map?

What's more appropriate - concat or map?

我想执行 2 个 promise,然后将 promise2 的结果传递给一堆其他 rxjs 运算符,以便在 promise2 解析时做一堆不同的事情。但我希望 promise2 仅在 promise1 解析时执行。为了获得这种效果,我应该使用类似

的东西吗?
from(promise1).pipe(
map(x => promise2),
tap((x) => console.log('response from map: ', x)),
other_rxjs_ops)
  .subscribe(...)

如果我使用 concat 而不是 map

concat(promise1, defer(() => promise2)).pipe(
tap(console.log('response from map: ', x)),
other_rxjs_ops))
  .subscribe(...)

我假设会发生的事情是 promise1 将执行,如果它解析,promise2 将执行,然后两个 promise 的结果将通过其他 rxjs 运算符并被订阅,对吗?

那么我使用 map 获得所需结果的方法是否合适,或者我应该考虑使用另一个 rxjs 运算符来执行 promise1 和 promise2?我 运行 在使用 map 时遇到的一个问题是 tap 中的 console.log 似乎在 map 中的承诺已解决或出错之前执行,并且控制台打印以下内容:

response from map: undefined //presuming promise2 hasn't had a chance to resolve yet, which is why we're getting undefined because the promise is designed to return a string value.

使用 concatMap 而不是 map 解决了这个问题,但我不明白为什么 tap 的行为方式与 map 一起使用时的行为方式。对此的任何指导也会有所帮助。

在您的情况下,您可以使用 Higher-Order RxJS mapping operators 之一,例如 concatMapmergeMapswitchMap,将流相互合并。

您可以尝试以下操作:

from(promise1)
  .pipe(
    // promise2 won't be executed until the promise1 is resolved.
    concatMap((val1) => from(promise2)),
    // tap won't be executed until the promise2 is resolved.
    tap((val2) => console.log('response from promise2:', val2))
    // Other RxJS operators here...
  )
  .subscribe();

备注:

  • map 运算符用于将值转换为另一种类型,在您的情况下,它用于将 promise1 结果转换为 Promise,但是,它不会'订阅它也没有将它转换为Observable,所以tap转换后直接执行,而不是等待它被解析。
  • (可选)要订阅 promise1,应使用 from 函数将其转换为 Observable
  • 要订阅新的 Observable,它应该与原来的 from(promise1) 合并,使用 higher-order 映射运算符之一,而不是使用正常的 map

关于你的第一个选择

您正在使用 map 运算符,发现 tap 没有等待 promise 被解析。

所以这里发生了什么,map 运算符不订阅内部可观察对象,因此它返回 promise 对象 (Promise {}) 并且不会等待待解决,因为 tap 操作员在这里记录这个 - response from map: Promise {}

任何高阶映射(concatMap mergemap switchMap ExhaustMap) 订阅内部observable.Know more: link1 | Link2

因此在这段 concatMap(x => promise2) 代码中,concatMap 将订阅 promise2 并在 promise2 得到解析时发出数据。

第一个选项使用 concatMap

from(promise1)
  .pipe(
    concatMap((x) => promise2),
    tap((x) => console.log('response from map: ', x))
    // other_rxjs_ops...
  )
  .subscribe();

在你的情况下 source observablefrom(promise1) 一旦 promise1 是 resolved.After 从 promise1 收到响应,concatMap 将订阅 promise2

一个 Promise 只能发出一个数据,要么 resolve 要么 reject,所以你也可以在这里使用 mergeMap 或任何更高阶的 map 运算符。

所以你可以考虑第一个选项如果你需要使用promise1响应调用promise2

现在进入您的第二个选项,它使用concat

因此,如果 promise2 不依赖于 promise1 的响应,您可以考虑第一个选项。

简单地说,您的要求是在 promise1

完成后调用 promise2

我提供了一个工作示例,您可以通过它来解决您的疑虑

import { concat, from, interval, of } from 'rxjs';
import {
  concatMap,
  exhaustMap,
  map,
  mergeMap,
  switchMap,
  take,
  tap,
} from 'rxjs/operators';

const source = interval(1000).pipe(take(5));

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Promise1 resolved!');
    // reject('Promise1 rejected!');
  }, 5000);
});

/*..............Option 1..............*/
source
  .pipe(
    mergeMap((result) => {
      console.log("Inside pipe: ",result);
      return promise1;
    })
    // concatMap(()=>promise1),
  )
  .subscribe({
    next: console.log,
    error: console.error,
    complete: () => console.log('Completed!'),
  });

// source.pipe(
//   tap(console.log),
//   map(()=>promise1),
// ).subscribe(console.log);

/*..............Option 2..............*/

concat(source, promise1).subscribe({
  next: console.log,
  error: console.error,
  complete: () => console.log('Completed!'),
});