尝试使用 Ionic 3 中的 switchMap 取消现有的 http 请求
Trying to cancel existing http request with new one using switchMap in Ionic 3
我的目标是在 Ionic 3 项目中使用 RxJs switchMap
,在服务器离线时取消任何正在进行的登录尝试,并且只使用最新的请求。否则我以后可能会得到一些不需要的异步副作用。
在我的视图层中,我使用 submitStream$
来捕获按钮点击流,然后将其作为方法参数传递给服务层。
在服务层,我通过 switchMap
创建 response$
,将传递的参数 submitStream$
与从 this.webServiceUtil.testLogin()
返回的 Observable<Response>
相结合。
我尝试实现此代码:
HTML 标记
<button #submit type="submit">Submit</button>
打字稿:视图层
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { ElementRef, ViewChild } from '@angular/core';
export class LoginPage {
@ViewChild('submit') button: ElementRef
submitStream$:any;
...
ionViewDidLoad() {
this.submitStream$ =
Observable.fromEvent(this.button.nativeElement, 'click')
}
...
}
Typescript:服务层(submitStream$ 作为方法参数出现)
this.response$ = submitStream$.switchMap(click =>
this.webServiceUtil.testLogin())
我也试过在 ngAfterViewInit()
中创建 this.submitStream$
当事情不起作用时,我也尝试将其附加到 Observable.fromEvent:
.subscribe(ev => {
console.log('LoginPage: ionViewDidLoad() submitStream$.subscribe(): ev:', ev);}
)
看来您必须做一些时髦的事情才能使您订阅的内容在 RxJs 眼中看起来正确...
这就是我为解决错误类型错误所做的工作:无效的事件目标:
@ViewChild('submit') button: any;
this.submitClickStream$ =
Observable.fromEvent(this.button._elementRef.nativeElement , 'click')
.subscribe(ev => {
console.log('ev: ', ev);},
(err) => {console.error(err);}
);
在 AuthService 中,传递 submitClickStream$
或来自 @ViewChild 的按钮元素,并在 AuthService 中对其执行 Observable.fromEvent,我是无法通过事件的控制台日志记录获得订阅,无法触发。
所以,我引入了一个 BehaviourSubject 中介。
我可以在 LoginPage.html 的 <button>
元素中再次使用常规 (click)='onSubmit()'
。
在LoginPage.ts的onSubmit()方法中,我可以直接使用this.clickStream$.next('');
的BehaviourSubject。
这消除了 Observable.fromEvent 和 ViewChild 的复杂性。
switchMap 终于成功了,取消了之前正在进行的请求,没有混乱的退订逻辑。
LoginPage.ts
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { AuthService } from './../../providers/auth-service';
import { LoginCredentials } from './../../model/loginCredentials';
export class LoginPage {
private clickStream$:BehaviorSubject<any>;
constructor(
private authService:AuthService,
) {
this.clickStream$ = new BehaviorSubject('');
}
onSubmit():void {
console.log('LoginPage: onSumbit()');
this.clickStream$.next('');
this.authService
.login(this.prepareCredentials(),
this.clickStream$
);
}
}
AuthService
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { LoginCredentials } from './../../model/loginCredentials';
import { WebServiceUtil } from './web-service-util';
@Injectable()
export class AuthService {
login(
loginCredentials: LoginCredentials,
clickStream$: BehaviorSubject<any>
) {
this.response$ = clickStream$.switchMap(click => {
console.log('AuthService: login() : click: ', click);
return this.webServiceUtil.testLogin();
}
);
this.response$.subscribe(
(response:Response) => {....},
(err) => {console.error(err); ....}
}
}
WebServiceUtil
@Injectable()
export class WebServiceUtil {
testLogin(
): Observable<Response> {
...
}
}
你们非常亲密。请使用如下所示的开关图。希望对您有所帮助!
this.submitStream$ = Rx.Observable.fromEvent(this.button._elementRef.nativeElement, 'click');
this.submitStream$
.switchMap(click => {
return this.dummyAPIResponse(); // this should return observalbe(i.e new observalbe)...
})
.subscribe((res) => {
console.log(res);
});
dummyAPIResponse(){
return Rx.Observable.create(observer => {
setTimeout(() => {
observer.next([1, 2, 3, 4]);
}, 10000);
});
}
我的目标是在 Ionic 3 项目中使用 RxJs switchMap
,在服务器离线时取消任何正在进行的登录尝试,并且只使用最新的请求。否则我以后可能会得到一些不需要的异步副作用。
在我的视图层中,我使用 submitStream$
来捕获按钮点击流,然后将其作为方法参数传递给服务层。
在服务层,我通过 switchMap
创建 response$
,将传递的参数 submitStream$
与从 this.webServiceUtil.testLogin()
返回的 Observable<Response>
相结合。
我尝试实现此代码:
HTML 标记
<button #submit type="submit">Submit</button>
打字稿:视图层
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { ElementRef, ViewChild } from '@angular/core';
export class LoginPage {
@ViewChild('submit') button: ElementRef
submitStream$:any;
...
ionViewDidLoad() {
this.submitStream$ =
Observable.fromEvent(this.button.nativeElement, 'click')
}
...
}
Typescript:服务层(submitStream$ 作为方法参数出现)
this.response$ = submitStream$.switchMap(click =>
this.webServiceUtil.testLogin())
我也试过在 ngAfterViewInit()
this.submitStream$
当事情不起作用时,我也尝试将其附加到 Observable.fromEvent:
.subscribe(ev => {
console.log('LoginPage: ionViewDidLoad() submitStream$.subscribe(): ev:', ev);}
)
看来您必须做一些时髦的事情才能使您订阅的内容在 RxJs 眼中看起来正确...
这就是我为解决错误类型错误所做的工作:无效的事件目标:
@ViewChild('submit') button: any;
this.submitClickStream$ =
Observable.fromEvent(this.button._elementRef.nativeElement , 'click')
.subscribe(ev => {
console.log('ev: ', ev);},
(err) => {console.error(err);}
);
在 AuthService 中,传递 submitClickStream$
或来自 @ViewChild 的按钮元素,并在 AuthService 中对其执行 Observable.fromEvent,我是无法通过事件的控制台日志记录获得订阅,无法触发。
所以,我引入了一个 BehaviourSubject 中介。
我可以在 LoginPage.html 的 <button>
元素中再次使用常规 (click)='onSubmit()'
。
在LoginPage.ts的onSubmit()方法中,我可以直接使用this.clickStream$.next('');
的BehaviourSubject。
这消除了 Observable.fromEvent 和 ViewChild 的复杂性。
switchMap 终于成功了,取消了之前正在进行的请求,没有混乱的退订逻辑。
LoginPage.ts
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { AuthService } from './../../providers/auth-service';
import { LoginCredentials } from './../../model/loginCredentials';
export class LoginPage {
private clickStream$:BehaviorSubject<any>;
constructor(
private authService:AuthService,
) {
this.clickStream$ = new BehaviorSubject('');
}
onSubmit():void {
console.log('LoginPage: onSumbit()');
this.clickStream$.next('');
this.authService
.login(this.prepareCredentials(),
this.clickStream$
);
}
}
AuthService
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { LoginCredentials } from './../../model/loginCredentials';
import { WebServiceUtil } from './web-service-util';
@Injectable()
export class AuthService {
login(
loginCredentials: LoginCredentials,
clickStream$: BehaviorSubject<any>
) {
this.response$ = clickStream$.switchMap(click => {
console.log('AuthService: login() : click: ', click);
return this.webServiceUtil.testLogin();
}
);
this.response$.subscribe(
(response:Response) => {....},
(err) => {console.error(err); ....}
}
}
WebServiceUtil
@Injectable()
export class WebServiceUtil {
testLogin(
): Observable<Response> {
...
}
}
你们非常亲密。请使用如下所示的开关图。希望对您有所帮助!
this.submitStream$ = Rx.Observable.fromEvent(this.button._elementRef.nativeElement, 'click');
this.submitStream$
.switchMap(click => {
return this.dummyAPIResponse(); // this should return observalbe(i.e new observalbe)...
})
.subscribe((res) => {
console.log(res);
});
dummyAPIResponse(){
return Rx.Observable.create(observer => {
setTimeout(() => {
observer.next([1, 2, 3, 4]);
}, 10000);
});
}