Rxjs 在激活ajax请求时切换缓冲区

Rxjs 在激活ajax请求时切换缓冲区,rxjs,Rxjs,我正在尝试实现一个缓冲区,这样我就可以在ajax请求运行时组合事件,这样它们就可以基本上批处理在一起,并在ajax请求未运行时发送。例如,如果我有这样的东西: const updateQueue$ = new Subject<ISettings>(); // nothing in flight right now so this should go straight to the server updateQueue$.next({ volume: 30 }); // previ

我正在尝试实现一个缓冲区,这样我就可以在ajax请求运行时组合事件,这样它们就可以基本上批处理在一起,并在ajax请求未运行时发送。例如,如果我有这样的东西:

const updateQueue$ = new Subject<ISettings>();

// nothing in flight right now so this should go straight to the server
updateQueue$.next({ volume: 30 });

// previous update is still in flight so queue this up
updateQueue$.next({ volume: 40 });
updateQueue$.next({ volume: 50 });
updateQueue$.next({ volume: 60, muted: true });

// original update finally finishes, combine all the latest 
// items and send them now which should look something like
// this: { volume: 60, muted: true }


const updateQueue$=new Subject();
//现在没有任何东西在飞行中,所以应该直接发送到服务器
updateQueue$.next({volume:30});
//上一次更新仍在进行中,请将其排队
updateQueue$.next({volume:40});
updateQueue$.next({volume:50});
updateQueue$.next({volume:60,mute:true});
//原始更新最终完成,合并所有最新版本
//项目并立即发送它们,看起来应该是
//此:{volume:60,muted:true}
我有一个stackblitz为这个,但它不完全工作,因为我想,我不知道为什么

const allowSend$=新行为主体(true);
const updateQueue$=新主题();
更新$
.asObservable()
.烟斗(
点击(项目=>log(“添加到updateQueue$”的项目),项目)),
//在我看来,我这里似乎出了点问题,但我没能指出它。这似乎从来没有运行过。
缓冲开关(
allowSend$.asObservable().pipe(过滤器(allowSend=>!allowSend)),
() =>
allowSend$.asObservable().pipe(
过滤器(allowSend=>allowSend),
轻触(()=>“关闭缓冲区”)
)
),
轻触(缓冲区内容=>
log(“bufferContents预过滤器”,bufferContents)
),
过滤器(buffer=>!!buffer.length),
映射(缓冲区内容=>{
返回Object.assign({},…bufferContents);
}),
轻触(bufferContents=>console.log(“组合缓冲区”,bufferContents)),
//发送网络请求
开关映射(值=>{
allowSend$.next(false);
返回sendToServer(值为任意值);
}),
点击(()=>allowSend$.next(true))
//推送至主题以允许下一个去模糊值通过
//点击(()=>allowNext$.next(true))
)
.订阅(响应=>{
日志(“发送到服务器完成”);
});
间隔(2000年)
.烟斗(
地图(()=>{
updateQueue$.next(generateRandomEvent());
})
)
.subscribe();
您可以利用降低排放,直到指定的可观测排放。控制排放行为有两种设置:

  • 前导
    -允许第一次发射通过
  • 尾随
    -允许最后一次发射通过(发射“指定可观测”之前的最后一次发射)
我们的想法是使用
油门
降低排放,然后在http调用完成后,调用
。下一步
在触发器上观察,以便油门将恢复允许排放

我们可以使用它将所有排放累积到一个单一的变化对象中

因此,在简化形式中,这应该适用于您:

resume$=新主题();//用于告知“油门”允许排放
队列$=新主题();
工作$=此.queue$.pipe(
//将所有更新累积到单个更新对象中
扫描((acc,cur)=>({…acc,…cur}),{}),
节流(()=>this.resume$,{leading:true,training:true}),
concatMap(state=>this.updateState(state).pipe(
完成(()=>this.resume$.next())
))
);
由于
节气门
控制排放,我认为一次只有一种排放物能够通过,因此我认为无论您选择
开关映射
concatMap
合并映射
还是
排气映射
,行为都不会有任何区别

看看这个例子


在这里,我更新了您的:-)

,因此,如果不需要合并结果,这将起作用。这些“设置”中的一些可能不具备所有功能。我在这里更新了stackblitz的“GeneratorAndomeEvent”fn:。这就是为什么我认为我需要使用缓冲区,而不是节流阀或concatmap之类的东西。我可以在每次更新时发送所有设置并限制它,但如果可以的话,我会尽量避免。简单修复。我们只需在其中添加一个
扫描
,即可将所有排放物合并到一个物体中。它可能会发送冗余字段,但我认为这可能是最不复杂的解决方案。我更新了SB。我非常感谢您的帮助。不过出于好奇,有没有理由不使用缓冲区操作符之一?看起来它们就是为这种情况而设计的。老实说,我不熟悉缓冲区运算符,这对我来说似乎更简单(可能是因为我不熟悉缓冲区运算符!):-)
const allowSend$ = new BehaviorSubject<boolean>(true);
const updateQueue$ = new Subject<ISettings>();

updateQueue$
  .asObservable()
  .pipe(
    tap(item => log("item added to updateQueue$", item)),

    // It seems to me I have *something* wrong here, but I haven't been able to pin point it. This doesn't appear to ever run.
    bufferToggle(
      allowSend$.asObservable().pipe(filter(allowSend => !allowSend)),
      () =>
        allowSend$.asObservable().pipe(
          filter(allowSend => allowSend),
          tap(() => "closing buffer")
        )
    ),

    tap(bufferContents =>
      console.log("bufferContents pre filter", bufferContents)
    ),

    filter(buffer => !!buffer.length),

    map(bufferContents => {
      return Object.assign({}, ...bufferContents);
    }),

    tap(bufferContents => console.log("combined buffer", bufferContents)),

    // Send network request
    switchMap(value => {
      allowSend$.next(false);
      return sendToServer(value as any);
    }),

    tap(() => allowSend$.next(true))

    // Push to subject to allow next debounced value through
    // tap(() => allowNext$.next(true))
  )
  .subscribe(response => {
    log("done sending to server");
  });

interval(2000)
  .pipe(
    map(() => {
      updateQueue$.next(generateRandomEvent());
    })
  )
  .subscribe();