Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 可观察的多个订阅_Javascript_Rxjs - Fatal编程技术网

Javascript 可观察的多个订阅

Javascript 可观察的多个订阅,javascript,rxjs,Javascript,Rxjs,我创建了自己的Observable,并为其订阅了两个函数。我希望对序列中的每个元素都执行这两个函数,但只执行最后一个 let observer=null const notificationArrayStream=Rx.Observable.create(函数(obs){ 观察者=obs; return()=>{} }) 函数触发器(某物){ 下一个(某事) } notificationArrayStream.subscribe((x)=>console.log('a:'+x)) notific

我创建了自己的
Observable
,并为其订阅了两个函数。我希望对序列中的每个元素都执行这两个函数,但只执行最后一个

let observer=null
const notificationArrayStream=Rx.Observable.create(函数(obs){
观察者=obs;
return()=>{}
})
函数触发器(某物){
下一个(某事)
}
notificationArrayStream.subscribe((x)=>console.log('a:'+x))
notificationArrayStream.subscribe((x)=>console.log('b:'+x))
触发器(‘测试’)
预期产量

a: TEST
b: TEST
实际产量

b: TEST
以下是JSBin:


为什么呢?我怎么能让多个函数订阅一个可观察的对象呢?

要让多个函数订阅一个可观察的对象,只需将它们订阅到该可观察对象,就这么简单。事实上你就是这么做的

但是您的代码不起作用,因为在执行
notificationArrayStream.subscribe((x)=>console.log('b:'+x))
之后,
observer
(x)=>console.log('b:'+x))
,所以
observer.next
将为您提供
b:TEST

所以基本上,这是你的可观察的创造是错误的。在
create
中,您传递了一个观察者作为参数,以便可以传递它的值。您需要通过自己的逻辑以某种方式生成这些值,但正如您所看到的,您的逻辑是错误的。如果你想把值推给观察者,我建议你使用一个主题

比如:

const notificationArrayStream = Rx.Observable.create(function (obs) {
  mySubject.subscribe(obs);
  return () => {}
})

function trigger(something) {
  mySubject.next(something)
}
主题 在您的情况下,您可以简单地使用
主题
。A允许您在将其用作一组订阅者和源的代理时,与多个观察者共享单个执行

本质上,以下是您使用主题的示例:

const subject = new Subject();

function trigger(something) {
    subject.next(something);
}

subject.subscribe((x) => console.log('a: ' + x));
subject.subscribe((x) => console.log('b: ' + x));

trigger('TEST');
结果:

a: TEST
b: TEST
a: TEST
b: TEST

陷阱:观察员来得太晚 请注意,订阅和广播数据的时间是相关的。如果您在订阅之前发送广播,则不会收到此广播的通知:

function trigger(something) {
    subject.next(something);
}

trigger('TEST');

subject.subscribe((x) => console.log('a: ' + x));
subject.subscribe((x) => console.log('b: ' + x));
结果:(空)


ReplaySubject和Behavior Subject 如果要确保将来的订户也能收到通知,可以使用或

下面是一个使用
ReplaySubject
的示例(缓存大小为5,这意味着最多可以记住5个过去的值,而行为Subject只能记住最后一个值):

结果:

a: TEST
b: TEST
a: TEST
b: TEST

您可以基于ReplaySubject构建包装器类Subscribable。它将比管理主体更干净,并且可以观察到:

export class Subscribable<T> {

    private valueSource: Subject = new ReplaySubject(1);
    public value: Observable;
    private _value: T;

    constructor() {
        this.value = this.valueSource.asObservable();
    }

    public set(val: T) {
        this.valueSource.next(val);
        this._value = val;
    }

    public get(): T {
        return this._value;
    }
}

原始文章:

每次订阅时,都会覆盖var observer

触发器函数只引用这一个变量,因此只有一个日志也就不足为奇了

如果我们将var设置为一个数组,它将按预期工作:


一个更干净的解决方案是使用,如上所述。

除了使用主题之外,还可以使用允许观察到的多播到多个订阅者:

const notificationArrayStream = Rx.Observable.create(function (obs) {
  observer = obs;
  return () => {}
}).pipe(publishReplay(), refCount())

可观测数据不是多播的;除非您使用任何类型的
主题
。当然,您可以创建主题,将
可观察的
输出像其他答案一样导入

但是,如果您已经有了
Observable
,使用
share()
可观察的
转换为
主题
共享重播(n)
,这将相当于
重播主题(n)

差不多就是这样。

constsubs=[]
常数ob=新的可观测值((s)=>{
console.log('called')
潜艇推进
})
常量触发器=(v)=>{
subs.forEach((sub)=>{
次建议修正案(五)
})
}
ob.订阅((v)=>{
console.log('ob1',v)
})
ob.订阅((v)=>{
console.log('ob2',v)
})
触发器(1)

把你的代码改成这样,它就会工作。这里的要点是,每个订阅都通过其相应的订阅服务器进行更新,如果您有多个订阅,则必须通知多个订阅服务器。在您的案例中,您刚刚通知了最后一个。

谢谢,主题是缺少的链接。供将来参考:“因为在执行(…)之后,观察者是
(x)=>console.log('b:'+x))
”为什么?你能再详细一点或者展示一下参考资料吗?好的,找到了参考资料我真的希望基本RXJS教程能提到主题(即,与事件发射器相比,没有多少解释,只是顺便多提一下)——如果没有这些主题,一出现复杂迹象,基本用例就会退化为非工作用例。看起来RXJS指南是为已经了解RXJS的人编写的(或者是在错误的假设下编写的,即寻找问题解决方案的开发人员会留下来阅读一本20页的指南)。这才是真正的答案。
let obs = [];

let foo = Rx.Observable.create(function (observer) {
  obs.push(observer);
});

function trigger(sth){
//   console.log('trigger fn');
  obs.forEach(ob => ob.next(sth));
}

foo.subscribe(function (x) {
  console.log(`a:${x}`);
});
foo.subscribe(function (y) {
  console.log(`b:${y}`);
});

trigger(1);
trigger(2);
trigger(3);
trigger(4);
const notificationArrayStream = Rx.Observable.create(function (obs) {
  observer = obs;
  return () => {}
}).pipe(publishReplay(), refCount())
import {share} from 'rxjs/operators';

let observer = null

const notificationArrayStream = new Observable(obs => {
  observer = obs;
}).pipe(share());

function trigger(something) {
  observer.next(something)
}

notificationArrayStream.subscribe((x) => console.log('a: ' + x))
notificationArrayStream.subscribe((x) => console.log('b: ' + x))

trigger('TEST')