GVKun编程网logo

Angular 中的 Subject vs BehaviorSubject vs ReplaySubject(angular injectable)

13

针对Angular中的SubjectvsBehaviorSubjectvsReplaySubject和angularinjectable这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Ang

针对Angular 中的 Subject vs BehaviorSubject vs ReplaySubjectangular injectable这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Angular 2事件发射器vs Subject、Angular 2路由器在Resolve中使用BehaviorSubject Observable、Angular BehaviorSubject 和错误异常、angular – BehaviorSubject过滤器不是一个函数?等相关知识,希望可以帮助到你。

本文目录一览:

Angular 中的 Subject vs BehaviorSubject vs ReplaySubject(angular injectable)

Angular 中的 Subject vs BehaviorSubject vs ReplaySubject(angular injectable)

我一直在寻找了解这 3 个:

  • 主题
  • 行为主体
  • 重播主题

我想使用它们并知道何时以及为什么,使用它们有什么好处,尽管我已经阅读了文档,观看了教程并搜索了谷歌,但我对此没有任何意义。

那么他们的目的是什么?一个真实的案例将不胜感激,它甚至不必编码。

我希望有一个清晰的解释,而不仅仅是“a+b => c you are subscribed to ....”

谢谢

答案1

小编典典

它实际上归结为行为和语义。带一个

  • Subject- 订阅者只会获得订阅 发出的发布值。问问自己,这是你想要的吗?订阅者是否需要了解有关先前值的任何信息?如果没有,那么您可以使用它,否则选择其他之一。例如,组件到组件的通信。假设您有一个组件在单击按钮时发布其他组件的事件。您可以使用带有主题的服务进行通信。

  • BehaviorSubject- 最后一个值被缓存。订阅者将在初始订阅时获得最新值。该主题的语义是表示随时间变化的值。例如登录用户。初始用户可能是匿名用户。但是一旦用户登录,那么新值就是经过身份验证的用户状态。

BehaviorSubject初始值初始化。这有时对编码偏好很重要。比如说你用null.
然后在您的订阅中,您需要进行空检查。也许没问题,也许很烦人。

  • ReplaySubject- 它可以缓存指定数量的排放。任何订阅者都将在订阅时获得所有缓存的值。你什么时候需要这种行为?老实说,我没有任何需要这种行为,除了以下情况:

如果您ReplaySubject使用 的缓冲区大小初始化 a 1,那么它实际上的 行为 就像 a
BehaviorSubject。最后一个值总是被缓存,所以它就像一个随时间变化的值。有了这个,就不需要像用 a
初始化null的情况那样进行检查了。在这种情况下,在第一次发布之前,不会向订阅者发送任何值。BehaviorSubject``null

所以它真的归结为你所期望的行为(至于使用哪一个)。大多数时候,您可能想要使用
aBehaviorSubject因为您真正想要表示的是“随时间变化的价值”语义。ReplaySubject但我个人认为用初始化的替换没有任何问题1

当你真正需要的是一些缓存行为时,你想要 避免 的是使用 vanilla
Subject例如,您正在编写路由保护或解析。您在该守卫中获取一些数据并将其设置在
serviceSubject中。然后在路由组件中订阅服务主题以尝试获取在防护中发出的值。哎呀。价值在哪里?它已经发出了,DUH。使用“缓存”主题!

Angular 2事件发射器vs Subject

Angular 2事件发射器vs Subject

在Angular 2中,Event Emitter和Subject宣布活动有什么区别?似乎事件发射器的声明不那么复杂…… Angular 2首选哪种方式?
dataRefreshEvent = new EventEmitter();

private companyDataAnnouncedSource = new Subject();
companyDataAnnouncedSource$= this.companyDataAnnouncedSource.asObservable();
没有太大区别. EventEmitter扩展了Subject.

Angular2团队强调了这样一个事实,即EventEmitter不应该用于组件和指令中的@Output()之外的任何其他东西.

Angular团队has stated,他们可能会改变EventEmitter的底层实现,并破坏使用EventEmitter的用户代码,而不是用于它的目的.这是主要的区别.

Angular 2路由器在Resolve中使用BehaviorSubject Observable

Angular 2路由器在Resolve中使用BehaviorSubject Observable

我正在尝试使用Resolve设置我的路由器配置,它从BehaviorSubject返回一个Observable.我在角4.0.0-beta8和角2.4.8路由器3.4.8中尝试了这个

这是我的服务:

@Injectable()
export class MyService {
    private _data: BehaviorSubject<Array<string>> = new BehaviorSubject(undefined);

    constructor() {}

    public getData(): Observable<Array<string>> {

        this._data.next(['test1','test2','test3']);

        let asObservable = this._data.asObservable().delay(1000);
        asObservable.subscribe((myData) => {
            console.log([myData,'this console message DOES show up']);
        });

        // if I return here,my component's constructor and ngOnInit never fire
        // return asObservable;

        let fakeObservable = Observable.of(['test1','test3']).delay(1000);
        fakeObservable.subscribe((fakeData) => {
            console.log([fakeData,'this console message shows up']);
        });

        console.log([asObservable,fakeObservable]);
            /* console log output
            Observable {
                _isScalar: false,operator: DelayOperator,source: Observable {
                    _isScalar: false,source: BehaviorSubject {
                        _isScalar: false,_value: ['test1','test3'],closed: false,hasError: false,isstopped: false,observers: Array[1],thrownError: null,value: ['test1','test3']
                    }
                }
            },Observable {
                _isScalar: false,source: ScalarObservable {
                    _isScalar: true,scheduler: null,'test3']
                }
            }
            */

        return fakeObservable; // this WILL reach my component constructor and ngOnInit
    }
}

这是我的决心

@Injectable()
export class MyResolver implements Resolve<Array<string>> {

    constructor(private myService: MyService) {}

    resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<Array<string>>|undefined {
        return this.myService.getData();
    }
}

这是路由器

RouterModule.forChild([{
    path: 'mypath',component: MyComponent,resolve: {
        data: MyResolver
    }
}]);

这是组件:

@Component({
    selector: 'my-component',template: '<Span>My Component</span>'
})
export class MyComponent implements OnInit {
    constructor(private route: ActivatedRoute) {
        console.log('component constructor');
    }

    ngOnInit(): void {
        console.log(this.route.snapshot.data['data']); // ['test1','test3']
    }
}

这可能不是设计解决方案和服务之间交互的最佳方式,因此我对那里的建议非常开放.但是,如果我不弄清楚为什么BehaviorSubject.asObservable()不起作用,我可能会发疯,但模拟的observable确实有效.

解决方法

我一夜之间想到了这一点,并意识到我正在使用解决方法.问题的关键在于路由器期望最终完成解析结果.尽管BehaviorSubject一次只有一个值,但它永远不会完成,因为该值总是可以改变.我将this._data.asObservable()更改为this._data.asObservable().first(),它开始工作.现在看起来很明显!

Angular BehaviorSubject 和错误异常

Angular BehaviorSubject 和错误异常

你不能简单地做一些像设置你的行为主题形状这样的事情:

data$ = new BehaviorSubject({
  users: [],error: null,create: false
});

并在您发现错误时设置 error 属性:

private createUser(user: User){
  this.http.post({body : user}).pipe(
    map((result) => result),catchError((err) => {
      if (err.error?.title === 'Custom' && err.status === 400) {
        ////Get and return exception
        this.data$.next({...this.data$.value,error: 'Your error message about the is statement'}); // Maybe err.message,whatever you want
        return throwError(err);
      } else {
        // Same here with error message about your else statement
        return throwError(err);
      }
     
      // And you should think about a default error message,err.message or whatever is returned
    })
  )
  .subscribe((response: any) => {
    if(response) {
      this.data$.next({...this.data$.value,create: true});
    }
  });
}

因此您将能够处理组件中的错误字段:

this.userService.data$.subscribe((data) => {
  if(!data.error) {
    this.router.navigate(['/users/user/list']);
  }
  // You can also display a snackbar with the error message if you want. Adapt it with your need,maybe you only want a boolean
});

angular – BehaviorSubject过滤器不是一个函数?

angular – BehaviorSubject过滤器不是一个函数?

花一些时间试图弄清楚为什么我的plunker不工作:(

https://plnkr.co/edit/JHODQeWQtYmz4UkYzFds?p=preview

错误附加在以下行

let load = this.actions$.filter (action => return action.type==START_LOADING);

actions $定义如下:

private actions$: BehaviorSubject<Action> = new BehaviorSubject<Action>({type: null,payload: null});

我导入了这个

import { Subject } from "rxjs/subject";
import { Observable } from "rxjs/Observable";
import { BehaviorSubject } from 'rxjs/subject/BehaviorSubject';

在Chrome的调试器中,我看到一些功能可用(地图,电梯,扫描等)但不过滤.

有人知道为什么过滤器在BehaviorSubject上不可用?我想这是一个简单的错误,但我找不到;)

解决方法

我认为你应该导入过滤器操作符:

import 'rxjs/add/operator/filter';

这是您更新的plunkr与此导入:https://plnkr.co/edit/37JEG4aQ7qmQuaPchB4Z?p=preview.

有关详细信息,请参阅此问题:

> Angular 2 HTTP GET with TypeScript error http.get(…).map is not a function in [null]

关于Angular 中的 Subject vs BehaviorSubject vs ReplaySubjectangular injectable的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Angular 2事件发射器vs Subject、Angular 2路由器在Resolve中使用BehaviorSubject Observable、Angular BehaviorSubject 和错误异常、angular – BehaviorSubject过滤器不是一个函数?等相关知识的信息别忘了在本站进行查找喔。

本文标签: