标签: rxjs6

Angular如何使用rxjs管道从observable中过滤数据

我在我的服务文件中调用了一个名为getWorkOrders()的方法,该方法又调用服务器来获取记录.

这是我的服务.我正在使用新的HttpClient.

export class BackendServices {
  private BASE_URL ='http://localhost:3000/backend';
  constructor(private http: HttpClient) {}
  getWorkOrders(){
    return this.http.get(this.BASE_URL + '/getworkorders/');
 }
}
Run Code Online (Sandbox Code Playgroud)

Component.ts文件

private woSubject = new BehaviorSubject<IWorkOrders[]>([]);
    getWorkOrders() {
        this.bs.getWorkOrders()
          .subscribe((data: any) =>
            this.woSubject.next(data),
        );
      }
Run Code Online (Sandbox Code Playgroud)

从组件getWorkOrders方法如何过滤从服务器获取的所有记录中的数据.我知道它正在使用管道和过滤器rxjs运算符,但不知道如何将它组合在一起.

在此输入图像描述

angular rxjs6

9
推荐指数
1
解决办法
1万
查看次数

如何将选定的角度下拉值绑定到标量值的Observable?

我有一个角度材质选择组件,我想将下拉列表的选定值绑定到来自firebase的Observable of scalar.我想这样做而不需要解开组件中的observable.它看起来我无法使用异步管道绑定值.下面的代码抛出一个异常,因为mat-select的值不能绑定到"uiStateSvc.currentClient $ | async".

<mat-form-field *ngIf="(store.authorizedClients$ | async)?.length > 0">
  <mat-select [(value)]="uiStateSvc.currentClient$ | async" [compareWith]="compareFn">
    <mat-option *ngFor="let client of store.authorizedClients$ | async" [value]="client"
    (onSelectionChange)="changeCurrentClient($event, client)">
      {{ client.name}}
    </mat-option>
  </mat-select>
</mat-form-field>
Run Code Online (Sandbox Code Playgroud)

我从firebase中提取下拉列表的当前选定值,如下所示:

this.selectedClient$ = this.authSvc.currentUser$.pipe(
      switchMap((x: firebase.User) => {
        if (x != null) {
          return this.afs.doc(`uistate/${x.uid}`).valueChanges().map((y: any) => y.selectedclient);
        } else {
          return Observable.of(null);
        }
      })
    );
Run Code Online (Sandbox Code Playgroud)

observable firebase angularfire2 angular rxjs6

9
推荐指数
1
解决办法
1012
查看次数

我如何模拟RxJs 6计时器?

我们最近从Angular 5更新到Angular 6,并使用它更新了RxJs 6.作为迁移的一部分,计时器使用率已从以下变化:

Observable.timer()
Run Code Online (Sandbox Code Playgroud)

timer()
Run Code Online (Sandbox Code Playgroud)

在我们的测试中有很多地方我们使用以下模式模拟计时器可观察量.

let timerObserver: Observer<any>;

 beforeEach(() => {
 spyOn(Observable, 'timer').and.returnValue(Observable.create(
    ((observer: Observer<any>) => {
      timerObserver  = observer;
    })
  ));
});

it(`should not have any notifications by default`, () => {
   timerObserver.next('');
   ...
});
Run Code Online (Sandbox Code Playgroud)

有人知道如何迁移这种模式吗?


编辑:我在这里创建了一个简化的问题说明:

https://stackblitz.com/edit/angular-v6-testing-template-nm7add

// Hello.Component
      ngOnInit() {
        const timer$ = timer(30);
        timer$.subscribe(() => {
          this.testMe = 'this has been changed';
        });
      }

// Hello.component.spec
  it('should set testMe after a given timer', fakeAsync(() => {
    tick(50);
    expect(fixture.componentInstance.testMe).toBe('this has been changed');
  })); …
Run Code Online (Sandbox Code Playgroud)

jasmine angular rxjs6

9
推荐指数
1
解决办法
3084
查看次数

如何使用 RxJS 运算符避免多个嵌套订阅?

我正在使用 Angular 进行文件加密和上传类。其中许多操作是异步的,因此我编写的方法返回 RxJS Observables。

// 1.
private prepareUpload(file): Observable<T>;

// 2.
private encryptData(data, filekey): Observable<T>

// 3.
private uploadEncryptedData(formData, token, range): Observable<T>

// 4.
private completeUpload(updatedFilekey, token): Observable<T>
Run Code Online (Sandbox Code Playgroud)

我想将这个逻辑封装在一个公共upload(file)方法中,我最终使用了嵌套订阅,它可以工作,但我知道它是错误的,并且是 RxJS 中的反模式,原因有几个。这是代码的简化版本:

public upload(file) {
    const gen = this.indexGenerator(); // generator function

    this.prepareUpload(file).subscribe(values => {
    const [response, filekey, data] = values;

    this.encryptData(data, filekey).subscribe(encryptedDataContainer => {
      const formData = this.prepareEncDataUpload(encryptedDataContainer.data, file.name)
      const range = this.getRange(file.size, gen.next().value);

      this.uploadEncryptedData(formData, response.token, range).subscribe(() => {
        if (range.isFinalPart) {
            this.completeUpload(encryptedDataContainer.updatedFilekey, response.token).subscribe(console.log);
        }
      });

    }); …
Run Code Online (Sandbox Code Playgroud)

angular rxjs6

9
推荐指数
1
解决办法
9457
查看次数

如何从RXJS 5.5.6模拟fromEvent函数?

我必须测试一个使用fromEvent observable函数的函数.在升级到'lettable'运算符之前,我只是这样做:

spyOn(Observable, 'fromEvent').and.callFake(mockFromEventFunction)
Run Code Online (Sandbox Code Playgroud)

但是现在,Rxjs已经改变了,Observable.fromEvent只是一个名为fromEvent的函数,它是这样导入的:(并以相同的方式使用)

import { fromEvent } from 'rxjs/observable/fromEvent';
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何在不知道它的父上下文的情况下使用Jasmine间谍实用程序来模拟该函数?

我建议这不起作用:

import * as FromEventContext from 'rxjs/observable/fromEvent';
...
spyOn(FromEventContext , 'fromEvent').and.callFake(mockFromEventFunction)
Run Code Online (Sandbox Code Playgroud)

现在我有一个解决方法将fromEvent包装在一个我知道上下文的Object中.但我想知道如何干净利落地解决这个问题.

提前致谢.

unit-testing jasmine rxjs5 angular rxjs6

8
推荐指数
1
解决办法
1521
查看次数

RxJS迁移5到6 - 取消订阅TakeUntil

在RxJS 6中取消订阅的最佳方法是什么?

我的'旧'RxJS 5代码看起来如此

export class MyComponent implements OnInit, OnDestroy {
  private ngUnsubscribe: Subject<any> = new Subject();

  this.myService.myEventEmitter
    .takeUntil(this.ngUnsubscribe)
    .subscribe(this.onDataPolling.bind(this));

  public ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }
}
Run Code Online (Sandbox Code Playgroud)

在迁移到RxJS 6时,我跑了rxjs-5-to-6-migrate并得到了

this.myService.myEventEmitter.pipe(
  takeUntil(this.ngUnsubscribe))
  .subscribe(this.onDataPolling.bind(this));
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为EventEmitter没有管道方法.

在RxJS 6中取消订阅的最佳方法是什么?

编辑:这在干净安装后确实有效,是在RxJS 6中取消订阅的最佳方式.

migration subscription rxjs rxjs6

8
推荐指数
2
解决办法
4484
查看次数

在Angular中使用shareReplay(1)-仍会调用http请求吗?

我创建了一个演示(ng-run),其中有一个调用Http请求的按钮。

当单击按钮时,我调用此方法:

public getData(){
 this._jokeService.getData().subscribe();
}
Run Code Online (Sandbox Code Playgroud)

依次调用此(从服务):

 public getData() {
    return this.http.get(API_ENDPOINT).pipe(shareReplay(1))
  }
Run Code Online (Sandbox Code Playgroud)

问题在于每次点击-我仍然看到启动了一个新的http请求:

在此处输入图片说明

题:

为什么shareReplay不保留响应的最后一个值?
如何使我的代码仅调用一次HTTP并保留该值以备将来使用?

编辑:解决方案在这里

javascript rxjs angular rxjs6

8
推荐指数
2
解决办法
3834
查看次数

如何正确链接 rxjs 6 observables?

任何建议,如何以更多的承诺链风格重写?:

this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
        map(() => {
            return this.apiService.sendGetRequest('/api/users/' + this.currentUserId).pipe(
                map(data => {
                    return this.setActiveUser(data).pipe(
                        map(() => {
                            return this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId).pipe(
                                map(tasks => {
                                    return this.taskService.setCurrentUserTasks(tasks);
                                })
                            );
                        })
                    );
                })
            );
        })
    );
Run Code Online (Sandbox Code Playgroud)

observable rxjs angular rxjs6

8
推荐指数
3
解决办法
9440
查看次数

将RxJS与filter(Boolean)一起使用进行查询?

我正在用代码段阅读一些代码:

search(query: string) {
  of(query).
  pipe(
    filter(Boolean), 
    debounceTime(300), 
Run Code Online (Sandbox Code Playgroud)

filter(Boolean)基本一样的东西filter(v=>!!v)

javascript rxjs typescript angular rxjs6

8
推荐指数
2
解决办法
945
查看次数

如何在 rxjs 6.4.0 Angular 中替换 flatMap 和 mergeMap

我的 Angular 7 应用程序中有一个拦截器,它在重新发出请求之前发出获取令牌的请求。如果同时出现多个请求,那么它们都会发出获取令牌的请求。为了避免这种情况,我共享一个可观察量,以便共享获取令牌的结果,并且只发出一个请求来获取令牌。

我创建共享可观察量如下

this.authService.sharedToken =   this.authService.getToken().pipe(share());
Run Code Online (Sandbox Code Playgroud)

然后我提出请求

 return auth.sharedToken.flatMap((res) => {

     auth.saveTokenToLocalStorage(res);
     return this.getRequestWithAuthentication(request, next, auth);

 }).catch(function (err) {// I handle errors here
 }
Run Code Online (Sandbox Code Playgroud)

问题是 flatMap 已被弃用,用 mergeMap 替换它也不起作用。看来 mergeMap 现在是一个独立的函数。那么我怎样才能让上面的代码工作呢?

我正在使用 rxjs 6.4.0 和 Angular 7.2.4

谢谢。

编辑:

使用新的管道方法我有以下内容:

  return auth.sharedToken.pipe(
            mergeMap((res) => {

                auth.saveTokenToLocalStorage(res);
                return this.getRequestWithAuthentication(request, next, auth);
            }), catchError(function (err) {
                console.log("failed to get token")
                return EMPTY;
            }));
Run Code Online (Sandbox Code Playgroud)

当请求失败时,我无法打印“无法获取令牌”。我在那里做了更多的错误处理,所以我需要在请求失败时触发一些代码。

rxjs angular rxjs6

8
推荐指数
1
解决办法
1万
查看次数