如何确保对观察者的订阅调用最初接收到最新的值
How do I ensure that a call to subscribe on the observer initially receives the most recent value?
我将rxjs
与Angular 2和Typescript一起使用。我想在多个组件之间共享一个通用的web资源(在我的应用程序上下文中是一个"项目",本质上是一个JSON文档)。为了实现这一点,我引入了一种服务,它公开了一个可观察的,将由所有客户端共享:
/**
* Handed out to clients so they can subscribe to something.
*/
private _observable : Observable<Project>;
/**
* Used to emit events to clients.
*/
private _observer : Observer<Project>;
constructor(private _http: Http) {
// Create observable and observer once and for all. These instances
// are not allowed to changed as they are passed on to every subscriber.
this._observable = Observable.create( (obs : Observer<Project>) => {
this._observer = obs;
});
}
客户端现在只需获得一个_observable
的引用并订阅它
/**
* Retrieves an observable that always points to the active
* project.
*/
get ActiveProject() : Observable<Project> {
return (this._observable);
}
当某个组件决定实际加载项目时,它会调用以下方法:
/**
* @param id The id of the project to set for all subscribers
*/
setActiveProject(id : string) {
// Projects shouldn't change while other requests are in progress
if (this._httpRequest) {
throw { "err" : "HTTP request in progress" };
}
this._httpRequest = this._http.get('/api/project/' + id)
.catch(this.handleError)
.map(res => new Project(res.json()));
this._httpRequest.subscribe(res => {
// Cache the project
this._cachedProject = res;
// Show that there are no more requests
this._httpRequest = null;
// Inform subscribers
this._observer.next(this._cachedProject)
console.log("Got project");
});
}
它基本上执行一个HTTP请求,将JSON文档转换为一个"适当"的实例,并调用this._observer.next()
来通知所有订阅者有关更改的信息。
但是,如果在之后订阅了,则在发出新的HTTP请求之前,什么都看不到。我发现rxjs
中有某种缓存(或重放?)机制似乎可以解决这个问题,但我不知道如何使用它。
tl;dr:如何确保对观察器上subscribe
的调用最初接收到最新的值?
额外问题:通过"将观察者从可观察对象中拉出"(在构造函数中),我本质上创建了一个主题吗?
BehaviorSubject
就是这样做的
import { BehaviorSubject } from 'rxjs/subject/BehaviorSubject';
...
obs=new BehaviourSubject(4);
obs.subscribe(); //prints 4
obs.next(3); //prints 3
obs.subscribe(); //prints 3
我通常使用shareReplay(1)
来实现这一点。使用这个带有1作为参数的运算符将确保最新发出的值将保存在缓冲区中,因此当有新的订阅者时,该值将立即传递给它。您可以查看文档:
var interval = Rx.Observable.interval(1000);
var source = interval
.take(4)
.doAction(function (x) {
console.log('Side effect');
});
var published = source
.shareReplay(3);
published.subscribe(createObserver('SourceA'));
published.subscribe(createObserver('SourceB'));
// Creating a third subscription after the previous two subscriptions have
// completed. Notice that no side effects result from this subscription,
// because the notifications are cached and replayed.
Rx.Observable
.return(true)
.delay(6000)
.flatMap(published)
.subscribe(createObserver('SourceC'));
function createObserver(tag) {
return Rx.Observer.create(
function (x) {
console.log('Next: ' + tag + x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
}
// => Side effect
// => Next: SourceA0
// => Next: SourceB0
// => Side effect
// => Next: SourceA1
// => Next: SourceB1
// => Side effect
// => Next: SourceA2
// => Next: SourceB2
// => Side effect
// => Next: SourceA3
// => Next: SourceB3
// => Completed
// => Completed
// => Next: SourceC1
// => Next: SourceC2
// => Next: SourceC3
// => Completed
额外问题:通过"把观察者从可观察的事物中拉出来"(in构造函数),我本质上创建了一个主题吗?
我不知道你的意思是什么,但不是。主体既是观察者又是可观察者,具有特定的语义。正如你所说,仅仅"把观察者从可观察的事物中拉出来"是不够的。关于主题语义,请看这里:不同RxJS主题的语义是什么?
相关文章:
- 如何使jQuery插件函数可调用以供独立使用,而不在集合上操作
- D3在一个调用中绘制不同的SVG形状,没有可见性
- 如何从Java/scala调用js美化程序
- 如何调用这个匿名 JavaScript 函数
- 如何从模块链中调用函数.导出到节点中
- 我需要从php调用javascript或jquery
- Chrome开发工具(如何知道我在调用哪个javascript对象)
- 单击按钮后如何逐个调用分区,上一个分区将隐藏
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- Twitter Bootstrap typeahead:使用“this”获取上下文/调用元素
- node.js:setInterval()正在跳过调用
- 如何在单击复选框后调用控制器方法
- 如何在JQuery函数中定义一个值,然后调用另一个函数并使用该值
- Twitter API JSON调用未获得最新的3条推文
- 仅显示 Google 表格中来自 api 调用的最新数据行
- 如何确保对观察者的订阅调用最初接收到最新的值
- 如何使用$.validator将验证和重复记录检查w.r.t.添加到最新记录.调用addMethod引导
- 从反复调用的承诺返回服务中获取最新数据
- 最新的敲除和jquery ui对话框出错:无法在初始化之前调用
- 在最新的更新后无法调用hammer js实例