我在我的服务文件中调用了一个名为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运算符,但不知道如何将它组合在一起.
我有一个角度材质选择组件,我想将下拉列表的选定值绑定到来自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) 我们最近从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) 我正在使用 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) 我必须测试一个使用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中.但我想知道如何干净利落地解决这个问题.
提前致谢.
在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中取消订阅的最佳方式.
我创建了一个演示(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并保留该值以备将来使用?
编辑:解决方案在这里
任何建议,如何以更多的承诺链风格重写?:
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) 我正在用代码段阅读一些代码:
search(query: string) {
of(query).
pipe(
filter(Boolean),
debounceTime(300),
Run Code Online (Sandbox Code Playgroud)
是filter(Boolean)
基本一样的东西filter(v=>!!v)
?
我的 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)
当请求失败时,我无法打印“无法获取令牌”。我在那里做了更多的错误处理,所以我需要在请求失败时触发一些代码。
rxjs6 ×10
angular ×9
rxjs ×5
jasmine ×2
javascript ×2
observable ×2
angularfire2 ×1
firebase ×1
migration ×1
rxjs5 ×1
subscription ×1
typescript ×1
unit-testing ×1