我正在使用RxJS的.auditTime(500)
操作(docs)作为尾随节流:我想每500毫秒最多发出一次服务器调用。
当服务器调用完成时,我需要询问是否有更多待处理的服务器调用,或者暂时是否清除了缓冲区,以便我可以以状态消息的形式将此信息传递给用户,例如“正在保存...”和“保存。”
这大致是看起来的样子。
saveToServerObservable
.do(() => {
// gets called every time
setStatus(Status.SAVING);
})
.auditTime(500) // wait 500 ms and emit no more than once per 500 ms
.flatMap(data => axios({
method: "post",
url: "/saveurl",
data: data,
}))
.map(response => response.data)
.do(data => {
// here I want to know whether there are pending values from the
// auditTime() operation above or if the buffer is currently clear
const pendingSaves = ???;
if (!pendingSaves) {
setStatus(Status.SAVED);
}
})
.subscribe();
正如您在最后的.do()
操作中所看到的,我想知道.auditTime(500)
操作中是否存在待定值。我怎样才能实现这样的目标呢?
干杯!
答案 0 :(得分:1)
我认为您可以使用scan
并稍微修改您的链来实现您想要的目标:
const inc = new Subject();
const dec = new Subject();
const counter = Observable.merge(dec.mapTo(-1), inc.throttleTime(500).mapTo(1))
.scan((acc, val) => acc + val, 0)
.map(val => val > 0);
saveToServerObservable
.do(() => {
// gets called every time
setStatus(Status.SAVING);
inc.next();
})
.auditTime(500) // wait 500 ms and emit no more than once per 500 ms
.flatMap(data => axios({
method: "post",
url: "/saveurl",
data: data,
}))
.do(() => dec.next())
.map(response => response.data)
.withLatestFrom(counter, (data, pendingSaves) => {
if (!pendingSaves) {
setStatus(Status.SAVED);
}
})
.subscribe();
整个想法位于合并counter
和inc
的{{1}} Observable中。这两个Observable使用dec
递增和递减计数器。
scan()
也与inc
相关联,与.throttleTime(500)
完全相反,因为当您致电.auditTime(500)
时,您始终知道这会使setStatus(Status.SAVING);
发出一个项目,因此你可以立即递增计数器。
然后.auditTime(500)
只是将计数器与远程调用的结果合并,这是您可以检查来自withLatestFrom
的最新发射的位置。
答案 1 :(得分:0)
增加和减少计数器太容易受到错误的影响,所以我最终采用了完全不同的方法。我现在分别跟踪本地数据是否“脏”。我使用这个脏信号向用户显示“Saving ...”vs“Saved”消息:
dirty
设置为true
。dirty
设置为false
。dirty
设置为true
我在每次用户进行编辑时定义Rx.Subject
。每次收到信号时,我都会将dirty
设置为true
。
// stream of signals to save the active document
const userEditSignal$ = new Rx.Subject();
const savePrototype = () => {
userEditSignal$.next();
};
userEditSignal$.subscribe(() => {
// runs for each call to save the active document
store.commit("SET_DIRTY", true);
});
dirty
状态以决定何时保存到服务器每当dirty
值发生变化时,我们就会知道这一点,这与每次设置时都不一样。
const observeState = (store, getter) => {
// irrelevant details redacted
}
// emits only when `dirty` changes, not every time it's set
const shouldSaveToServer$ = observeState(store, state => state.dirty);
此自定义时序逻辑取代了对auditTime()
运算符的需求。
const saveToServerSignal$ = shouldSaveToServer$.switchMap(shouldSave => {
return shouldSave ?
// as long as we should save, save every 500 ms
Rx.Observable.interval(500) :
// when we should not, stop
Rx.Observable.never();
});
// create a request object for each save-to-server signal
const saveRequest$ = saveToServerSignal$
.mapTo(store.state.activeDocument)
.map(createSaveRequest);
//
const saveResponse$ = saveRequest$
// sends immediately
.flatMap(request => axios(request));
如果他们同意,我们可以将dirty
设置为false
。
saveResponse$
.map(response => response.data)
.do(savedDocument => {
const activeDocument = store.state.activeDocument;
// update just `created`, `modified`, and `user`
store.commit({
type: "UPDATE_ACTIVE_DOCUMENT",
// irrelevant details omitted
});
// diff current state and saved document (function details omitted)
const activeAndSavedDocsMatch = diff(activeDocument, savedDocument);
if (activeAndSavedDocsMatch) {
store.commit("SET_DIRTY", false);
}
})
.subscribe();