为什么在使用Promise时,switchMap操作符只会发出最后一个值?

7

我有一些难以理解。当我在Observable中使用switchMap运算符时,它会按预期发出所有值:

Observable.from([1, 2, 3, 4, 5])
    .do(console.log)
    .switchMap(i => Observable.of('*' + i))
    .do(console.log)
    .subscribe();

结果:

1
*1
2
*2
3
*3
4
*4
5
*5

但是当我用 Promise 替换 Observable 时,行为会有所不同:

Observable.from([1, 2, 3, 4, 5])
    .do(console.log)
    .switchMap(i => new Promise((resolve) => resolve('*' + i)))
    .do(console.log)
    .subscribe();

结果:

1
2
3
4
5
*5
2个回答

3
这个代码按预期工作。你说的意外行为是因为Observable.fromObservable.of总是严格同步的,而new Promise不一定是这样的(我不确定所有浏览器都是这样规定的)。无论如何,你可以通过传递async调度器来强制Observable.from以异步方式发出信号。
import { Observable } from 'rxjs';
import { async } from 'rxjs/scheduler/async';

Observable.from([1, 2, 3, 4, 5], async)
    .do(console.log)
    .switchMap(i => new Promise((resolve) => resolve('*' + i)))
    .do(console.log)
    .subscribe();

现在每个输出都被放在一个新的框架中,就像Promise一样,并且输出结果与您预期的相同。请查看实时演示(打开控制台):https://stackblitz.com/edit/rxjs5-gfeqsn?file=index.ts

这非常有道理!但是你能解释一下为什么将发射的信息分别放在框架中会产生这种行为吗?我期望所有发射的信息都作为输出。(或者我可能没有理解switchMap的预期行为。)谢谢。@martin - Martin
1
这是因为 switchMap 接收到 1 并订阅了 new Promise()。然后在同一帧中,它接收到 2 并取消订阅之前的 Promise 并订阅新的 Promise。依此类推,直到 5 及其 Promise 最终结束帧,JS 才会计算另一个帧,在该帧中只有最后一个活动的 Promise 被解决。 - martin

0
尝试使用{{link1:mergeMap}},也许这就是你正在寻找的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接