- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我的应用程序中,我有一个返回这样的可观察对象的服务:
public genericService(params) {
//Do some stuff
//...
return this.http.post('http://foo.com', params)
.map((response) => {
//Do some generic stuff
//...
return someData;
})
.catch((error: any) => {
//Manage error in a generic way + do some generic stuff
//...
return Observable.throw(error);
});
}
let debouncePointer = debounceObservable(genericService, 200);
public genericServiceDebounce(params) {
return debouncePointer(params);
}
现在在另一个地方,我想这样调用我的函数
genericServiceDebounce(params)
.subscribe((response) => {
//Do some non-generic stuff
}, (error) => {
//Manage error in a non-generic way + do some non-generic stuff
});
但是我没有成功实现debounceObservable()函数。
我基于 Promise 等价物 (https://github.com/moszeed/es6-promise-debounce/blob/master/src/es6-promise-debounce.js) 尝试了这个实现:
debounceObservable(callback, delay, immediate?) {
let timeout;
return function () {
let context = this, args = arguments;
return Observable.create((observer) => {
let later = function () {
timeout = null;
if(!immediate) {
observer.next(callback.apply(context, args));
//observer.onCompleted(); // don't know if this is needed
}
};
let callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, delay);
if(callNow) {
observer.next(callback.apply(context, args));
//observer.onCompleted(); // don't know if this is needed
}
});
}
}
但这并没有像预期的那样工作。使用 Promises 时,返回 resolve(anotherPromise) 允许您调用:
genericServiceDebounce().then(response => {
})
当使用 Observables 时,返回 observer.next(anotherObservable) 返回一个嵌入的 observable,这意味着你应该调用:
genericServiceDebounce().subscribe(obs => {
obs.subscribe(response => {
})
})
您将如何实现 debounceObservable() 函数?(以类似于 Promise 的方式)
澄清 1:我找到了 Observable.debounce() 函数,但这会去抖观察者而不是可观察对象本身。我想去除可观察的抖动
澄清 2:我将去抖动放在服务端,因为它是单例,并且它们是多个调用者。如果我将它放在调用方,每个调用方都会有一个不同的去抖动计时器。
编辑:这是我试图解释我的问题的片段。只需单击不同的按钮即可查看不同的行为(更多解释在 js 代码注释中)。
Observable.debounce 展示了 RxJs 中的 .debounce() 是如何工作的。它只输出“3”,但我想要“1”、“2”、“3”。
Observable.debounce x3 展示了如果我调用代码 3 次而没有将我的整个函数包装在 debounce 中会发生什么。
Observable wrapped x3 显示了我想要获取的内容。我的整个函数都被包装了,但是如果你看一下代码,订阅部分很挑剔。
Promise x3 展示了使用 Promises 是多么简单。
let log = (logValue) => {
const list = document.querySelector('#logs');
const li = document.createElement('li');
li.innerHTML = logValue;
list.appendChild(li);
}
/* ************************ */
/* WITH OBSERVABLE.DEBOUNCE */
/* ************************ */
let doStuffObservable = () => {
Rx.Observable.create((observer) => {
log('this should be called only one time (observable.debounce)');
setTimeout(() => {
observer.next('observable.debounce 1');
observer.next('observable.debounce 2');
observer.next('observable.debounce 3');
}, 1000);
})
.debounce(500)
.subscribe((response) => {
log(response);
}, (error) => {
log(error);
});
}
/* *********************************** */
/* WITH OBSERVABLE WRAPPED IN DEBOUNCE */
/* *********************************** */
let doStuffObservable2 = (param) => {
return Rx.Observable.create((observer) => {
log('this should be called only one time (observable wrapped)');
setTimeout(() => {
observer.next('observable wrapped ' + param);
}, 1000);
})
}
let debounceObservable = (callback, delay, immediate) => {
let timeout;
return function () {
let context = this, args = arguments;
return Rx.Observable.create((observer) => {
let later = function () {
timeout = null;
if(!immediate) {
observer.next(callback.apply(context, args));
}
};
let callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, delay);
if(callNow) {
observer.next(callback.apply(context, args));
}
});
}
}
let doStuffObservable2Debounced = debounceObservable(doStuffObservable2);
/* ************* */
/* WITH PROMISES */
/* ************* */
let doStuffPromise = (param) => {
return new Promise((resolve, reject) => {
log('this should be called only one time (promise)');
setTimeout(() => {
resolve('promise ' + param);
}, 1000);
});
}
let debouncePromise = (callback, delay, immediate) => {
let timeout;
return function () {
let context = this, args = arguments;
return new Promise(function (resolve) {
let later = function () {
timeout = null;
if (!immediate) {
resolve(callback.apply(context, args));
}
};
let callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, delay);
if (callNow) {
resolve(callback.apply(context, args));
}
});
}
}
/* ******* */
/* SAMPLES */
/* ******* */
function doObservableDebounce() {
doStuffObservable();
// result :
// this should be called only one time (observable.debounce)
// observable.debounce 3
// this is not what i want, i want all three values in output
}
function doObservableDebounce3Times() {
doStuffObservable();
doStuffObservable();
doStuffObservable();
// result :
// this should be called only one time (observable.debounce)
// this should be called only one time (observable.debounce)
// this should be called only one time (observable.debounce)
// observable.debounce 3
// observable.debounce 3
// observable.debounce 3
// this is bad
}
function doObservableWrappedDebounce3Times() {
doStuffObservable2Debounced(1)
.subscribe((response) => {
log(response);
response.subscribe((response2) => {
log(response2);
}, (error) => {
log(error);
})
}, (error) => {
log(error);
});
doStuffObservable2Debounced(2)
.subscribe((response) => {
log(response);
response.subscribe((response2) => {
log(response2);
}, (error) => {
log(error);
})
}, (error) => {
log(error);
});
doStuffObservable2Debounced(3)
.subscribe((response) => {
log(response);
response.subscribe((response2) => {
log(response2);
}, (error) => {
log(error);
})
}, (error) => {
log(error);
});
// result :
// AnonymousObservable { source: undefined, __subscribe: [Function] }
// this should be called only one time (observable wrapped)
// observable wrapped 3
// this is good but there are 2 embedded subscribe
}
function doPromiseDebounce3Times() {
let doStuffPromiseDebounced = debouncePromise(doStuffPromise);
doStuffPromiseDebounced(1).then(response => {
log(response);
})
doStuffPromiseDebounced(2).then(response => {
log(response);
})
doStuffPromiseDebounced(3).then(response => {
log(response);
})
// result :
// this should be called only one time (promise)
// promise 3
// this is perfect
}
<!DOCTYPE html>
<html>
<head>
<script data-require="rxjs@4.0.6" data-semver="4.0.6" src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
</head>
<body>
<button onclick='doObservableDebounce()'>Observable.debounce</button>
<button onclick='doObservableDebounce3Times()'>Observable.debounce x3</button>
<button onclick='doObservableWrappedDebounce3Times()'>Observable wrapped x3</button>
<button onclick='doPromiseDebounce3Times()'>Promise x3</button>
<ul id="logs"></ul>
</body>
</html>
最佳答案
抱歉,我没有收到您对我的评论的回复通知。
针对此问题的更简洁的 Rx-only 解决方案是将您的服务调用视为事件流,如下所示:
constructor() {
this._genericServiceCall$ = new ReplaySubject(1);
this._genericServiceResult$ = this._genericServiceCall$
.asObservable()
.debounceTime(1000)
.switchMap(params => this._genericService(params));
}
private _genericService(params) {
//Do some stuff
//...
return this.http.post('http://foo.com', params)
.map((response) => {
//Do some generic stuff
//...
return someData;
})
.catch((error: any) => {
//Manage error in a generic way + do some generic stuff
//...
return Observable.throw(error);
});
}
public genericService(params) {
this._genericServiceCall$.next(params);
return this._genericServiceResult$; // Optionally add `.take(1)` so the observer has the expected behaviour of only getting 1 answer back
}
虽然我看到了一些东西......您会接受哪些参数
作为必须通过私有(private)_genericService
的参数?
无论如何,你知道这里发生了什么吗?因此,每次有人调用 genericService()
时,它不会立即调用服务 - 相反,它会发出一个新的 _genericServiceCall$
并返回 _genericServiceResult$
流。如果我们看一下这个流是如何定义的,我们会发现它采用去抖动的 _genericServiceCall$
然后将其映射到服务调用。理论上它应该可以工作 - 还没有尝试过。
编辑:现在我明白了——您可能需要发布 genericServiceResult 以使其成为热可观察对象,否则它会在任何观察者订阅它时立即返回:
constructor() {
this._genericServiceCall$ = new ReplaySubject(1);
this._genericServiceResult$ = this._genericServiceCall$
.asObservable()
.debounceTime(1000)
.switchMap(params => this._genericService(params))
.publish();
const subscription = this._genericServiceResult$.connect();
// You must store subscription somewhere and dispose it when this object is destroyed - If it's a singleton service this might not be needed.
}
关于 Angular : how to debounce an Observable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47577863/
一段时间后,我阅读了有关 RxJava concat 的内容,并决定测试一下我的理解力。但是我遇到了一些我不太理解的行为。 问题是,当我连接两个可观察对象时,根据我将它们传递给 Observable.
我正在使用来自数据库服务的数据实现自动完成: @Injectable() export class SchoolService { constructor(private db: AngularF
我正在尝试使用 RxJS 创建一个可观察的对象,它可以执行如图所示的操作。 获取一个值并等待一段固定的时间才能获得 下一个。 下一个将是该周期内发出的最后一个值 等等,跳过其余部分。 如果等待时间间隔
我有一个可观察对象和另一个提供的可观察对象改变 key 。我想构建一个在之间切换的可观察对象基于该键的对象中的可观察值。 示例: // Choose randomly between "up" or
我使用 protobuffers 在我的前端和我的 Dart 服务器之间进行通信。 那些对象没有实现 Observable . 我的 Dart 聚合物对象看起来像: @CustomTag('user-
在 java swing 项目中,我有一个模型类,它保存某个 JPanel 的状态。我需要使这些数据可供 View 使用。我认为有两种选择。有一个扩展 Observable 的类并将模型作为实例变量。
我想找到一种方法来检测观察者是否已完成使用我使用 Rx.Observable.create 创建的自定义可观察对象,以便自定义可观察对象可以结束它并正确地进行一些清理。 因此,我创建了一些测试代码,如
我正在尝试查询数据库。迭代结果列表,并为每一项再执行一个请求。在 rxjs 构建结束时,我有 Observable[]> 。但我需要Observable 。如何做到这一点? this.caseServ
我希望我的 api 上有一个方法返回 Observable> 但我希望该方法中的代码知道所有包含的 Observables 是否已完成,以便它可以关闭某些内容。最好的方法是什么? 更明确地说,我希望完
我有两个方法返回 Observable> firstAPI.getFirstInfo("1", "2"); secondApi.getSecondInfo(resultFirstObservable,
我有一个 Observable返回单个 Cursor实例(Observable)。我正在尝试利用 ContentObservable.fromCursor获取 onNext 中每个游标的行回调。 我想
我有两种返回 Observable 的方法: Observable firstObservable(); Observable secondObservable(String value); 对于第一
我正在尝试创建一个将用户数据作为 Observable 的函数,并使用来自第一个 observable 的数据从查询中添加/合并数据,然后将所有这些数据作为一个 observable 返回,我可以这样
我有一个 spec-compliant ECMAScript Observable ,具体来自 wonka library .我正在尝试将这种类型的 observable 转换为 rxjs 6 obs
为了简化问题,我在这里使用了数字和字符串。代码: const numbers$:Observable = of([1,2,3]); const strings: string[] = ["a","b"
对于我的 Android 应用程序,我需要一个 Observable 来聚合来自 7 个不同搜索的结果并作为一个集合发出。 对于最终发射,我选择了 ListMultimap其中 Content是搜索结
我正在使用改造 2.0.0-beta2 并且调试构建工作正常,但我在使用 Proguard 发布构建时遇到以下错误。 这是更新后的 logcat 错误。 11-17 18:23:22.751 1627
observer.throw(err) 和 observer.error(err) 有什么区别? 我正在使用 RxJS 版本“5.0.0-beta.12” var innerObservable =
我们有一种情况,对服务的方法调用返回一个 IObservable但我们的客户期望 IObservable .将 T1 转换为 T2 很简单。 Rx 中有什么允许这样做的吗? (即链接观察者) 我知道我
我陷入了如何将以下可观察类型转换/转换为我的目标类型的困境: 我有可观察的类型: Observable>> 我想将其转换为: Observable> 所以当我订阅它时,它会发出 List不是Obser
我是一名优秀的程序员,十分优秀!