如何使用 2 个可观察量发出的值作为 http 请求的参数,其中 1 个可观察量将另一个重置为默认

我正在订阅一个基于其他 2 个可观察量的映射可观察量。每当两者中的任何一个发出值时,我希望映射的可观察值发出。


每当外部可观察值发出时,内部可观察值应重置为默认值(示例中为 0)。问题是,当我重置内部值时,会发出一个额外的值。


(对于上下文 - 2 个可观察量为 http 请求提供参数,这是映射的可观察量。新的外部值应将内部值重置为 0)


const outer = new Subject();

const inner = new BehaviorSubject(0);

const http = of("");

let mapped = outer.pipe(

  tap(() => inner.next(0)),

  switchMap(outerVal => {

    return inner.pipe(map(innerVal => ({ innerVal, outerVal })));

  }),

  switchMap(({ innerVal, outerVal }) => {

    return http.pipe(tap(() => console.log("http: ", outerVal, innerVal)));

  })

);


mapped.subscribe(result => {

  console.log(result);

});


outer.next("first");

inner.next(1);

inner.next(2);

outer.next("second");

inner.next(3);



// http: first 0

// http: first 1

// http: first 2

// http: first 0 <--- extra

// http: second 0

// http: second 3

我知道为什么会发生这种情况,但我不知道如何处理。我有一个解决方案,可以在该 stackblitz 的底部获得正确的结果,但我认为它会导致内存泄漏。


https://stackblitz.com/edit/rxjs-mxc5wq?file=index.ts


GCT1015
浏览 87回答 2
2回答

手掌心

以下有您想要的输出。我不确定它是否符合您的标准。你内心的可观察是否有理由必须成为行为主体?如果只是给它一个初始值,那么startWith操作员会做得更干净。const outer = new Subject();const inner = new Subject();const http = of("");const mapped = outer.pipe(&nbsp; switchMap(outerVal =>&nbsp; &nbsp; inner.pipe(&nbsp; &nbsp; &nbsp; startWith(0),&nbsp; &nbsp; &nbsp; map(innerVal => ({ innerVal, outerVal }))&nbsp; &nbsp; )&nbsp; ),&nbsp; switchMap(({ innerVal, outerVal }) =>&nbsp;&nbsp; &nbsp; http.pipe(&nbsp; &nbsp; &nbsp; tap(() => console.log("http: ", outerVal, innerVal))&nbsp; &nbsp; )&nbsp; ));mapped.subscribe(console.log); // ""你的 stackblitz 内存泄漏您正在创建长期存在的多播流,但从未完成它们。你可以尝试:tap(() => {&nbsp; inner2.complete();&nbsp; inner2 = new BehaviorSubject(0);}),SwitchMap 将取消订阅,但多播流在取消订阅时不会完成(取决于其refcount工作原理)。

BIG阳

考虑下面的方法,我将两个Observable流和过滤器组合起来只发出 1 个值。然后我们可以使用新的流与http请求合并const http = of("");const triggerSubject$ = new BehaviorSubject({ inner: 0, outer: null });const trigger = triggerSubject$.pipe(  filter(({ inner, outer }) => inner && outer));const triggerInner = val => {  console.log("Inner", val);  return triggerSubject$.next({    inner: val,    outer: triggerSubject$.value.outer  });};const triggerOuter = val => {  console.log("Outer", val);  return triggerSubject$.next({ inner: 0, outer: val });};const mapped = trigger.pipe(  switchMap(({ inner: innerVal, outer: outerVal }) =>    http.pipe(tap(() => console.log("http: ", outerVal, innerVal)))  ));mapped.subscribe(result => {  console.log(result);});triggerOuter("first");triggerInner(1);triggerInner(2);triggerOuter("second");triggerInner(3);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript