如何在新订阅中将所有值发布到Observer?

时间:2018-04-05 20:14:24

标签: javascript angular rxjs

我有一个观察者,随着时间的推移会发布不同的值。例如

using (var ctx = new ContractDbContext())
using (var transaction = ctx.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted))
{
    //any reads we do here will also read uncommitted data
}

如果#hack 1中有订阅,则应获取所有值1,2,3,如果#hack 2中有订阅,则应获取所有值1,2,3,4,5,6。 此外,ReplaySubject获取旧值,当然,但我希望每次发布都有所有值。因此,在每个sub.next(7)上,我需要所有值1,2,3,4,5,6和7.所以基本上observable存储所有已发布或'next'-ed值。 我如何实现这一目标?

3 个答案:

答案 0 :(得分:3)

BehaviorSubjectscan :)一起使用它基本上与Map.reduce相似,但会在每次更新时发出。

import { Component } from '@angular/core';

import { scan } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Component({
  selector: 'my-app',
  template: `
  <input (keydown.enter)="onMessage(input.value); input.value =''" #input />

  <div *ngFor="let message of messages$ | async">
    {{ message }}
  </div>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private messagesSource = new BehaviorSubject<any>([]);
  messages$ = this.messagesSource.asObservable()
    .pipe(scan((acc, curr) => [...acc, curr], []));

  onMessage(val: string) {
    this.messagesSource.next(val);
  }
}

Live demo

这一行是所有神奇的东西:scan((acc, curr) => [...acc, curr])它将主题发出的每个值汇总成一个数组。

答案 1 :(得分:2)

我喜欢@ TomaszKula的答案,但我认为这个问题是关于连续订阅以及之前(和将来)的发布。

据我所知,ReplaySubject做了所要求的......

&#13;
&#13;
console.clear()
const sub = new Rx.ReplaySubject();
sub.next(1); 
console.log('1st subscribe')
sub.subscribe(x => console.log('1st', x))
sub.next(2);
console.log('2nd subscribe')
sub.subscribe(x => console.log('2nd', x))
sub.next(3)
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

答案是:您不能使用简单的主题,因为您只能在订阅中访问它的值,但绝不能在您的服务中本地访问它。使用BehaviorSubject即可。

但首先,请将您的主题设为私有,并且只能通过方法访问。然后你可以这样做魔术:

import { Injectable } from '@angular/core';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class DataService {

   private subject = new BehaviorSubject<string>();

   setData(data: string) {
     this.subject.next(
       this.subject.getValue() + ',' + data;
     );
   }

   clearData() {
     this.subject.next();
   }

   getData(): Observable<any> {
      return this.subject.asObservable();
   }

}

您的订阅者以这种方式访问​​此BehaviorSubject

constructor(private dataService:DataService){}

ngOnInit(): void {
   this.dataService.getData().subscribe(data => {
      // do something with data
   });
}

private aMethod(): void {
   this.dataService.setData(aString);
}