为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

GCT1015 2023-07-14 09:56:01
我正在订阅一个基于其他 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
查看完整描述

2 回答

?
手掌心

TA贡献1942条经验 获得超3个赞

以下有您想要的输出。我不确定它是否符合您的标准。你内心的可观察是否有理由必须成为行为主体?如果只是给它一个初始值,那么startWith操作员会做得更干净。


const outer = new Subject();

const inner = new Subject();

const http = of("");


const mapped = outer.pipe(

  switchMap(outerVal =>

    inner.pipe(

      startWith(0),

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

    )

  ),

  switchMap(({ innerVal, outerVal }) => 

    http.pipe(

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

    )

  )

);


mapped.subscribe(console.log); // ""

你的 stackblitz 内存泄漏

您正在创建长期存在的多播流,但从未完成它们。你可以尝试:


tap(() => {

  inner2.complete();

  inner2 = new BehaviorSubject(0);

}),

SwitchMap 将取消订阅,但多播流在取消订阅时不会完成(取决于其refcount工作原理)。


查看完整回答
反对 回复 2023-07-14
?
BIG阳

TA贡献1859条经验 获得超6个赞

考虑下面的方法,我将两个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);


查看完整回答
反对 回复 2023-07-14
  • 2 回答
  • 0 关注
  • 84 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信