我的组件中有一个方法,它使用observable来监听第一个事件,并且超时为15秒。该方法调用嵌套的observable,如果参数为null或为空,则应抛出该错误。我使用Observable.throw()但错误仅在超时/ 15s之后传播。
this.signUp(this.user)
.first()
.timeout(15000)
.subscribe((authResponse) => {
console.log("next fired");
dialogs.alert("Next: " + authResponse);
}, (error) => {
//fired only after 15s when mobile is empty
console.log("error fired");
console.log(JSON.stringify(error));
}, () => {
console.log("completed fired");
});
注册()
public signUp(user: User): Observable<AuthResponse> {
let observable = new Subject<AuthResponse>();
this.isUserExisting(user.mobile)
.first()
.subscribe((isUserExisting) => {
if (isUserExisting) {
console.log("User already exists");
observable.next(AuthResponse.USER_EXISTING);
} else {
console.log("User does not exist");
this.saveUser(user).first().subscribe(() => {
observable.next(AuthResponse.SUCCESS);
})
}
}, (error) => {
return Observable.throw(error);
})
return observable;
}
public isUserExisting(mobile: string): Observable<boolean> {
let observable = new Subject<boolean>();
if (!mobile) {
console.log("empty mobile");
return Observable.throw(new Error("Mobile number cannot be empty"));
}
firebase.query(() => { }, "/users",
{
singleEvent: true,
orderBy: {
type: firebase.QueryOrderByType.CHILD,
value: "mobile"
},
range: {
type: firebase.QueryRangeType.EQUAL_TO,
value: mobile
}
}
).then((result) => {
console.log("Checking for user success: ");
console.log(JSON.stringify(result));
observable.next(result.value != null);
});
return observable;
}
更新: saveUser()
public saveUser(user: User) {
return Observable.defer(() => firebase.push('/users', user)
.then((result) => {
console.log("Created user record with key: " + result.key);
console.log("Dumping result:");
console.log(JSON.stringify(result));
})
.catch((error) => {
console.log("Error while saving user: " + error);
})
)
}
答案 0 :(得分:1)
创建您自己的主题是一种不好的做法,您将在该主题上发出由内部订阅的observable发出的可观察值。这会导致内存泄漏,因为您无法取消订阅内部订阅。
public signUp(user: User): Observable<AuthResponse> {
return this.isUserExisting(user.mobile)
.flatMap(isExistingUser => {
if (isExistingUser) {
console.log('user already exists: ' + isUserExisting);
return Rx.Obserable.of(AuthResponse.USER_EXISTING);
}
return saveUser(user).map(result => AuthResponse.SUCCESS)
})
.catch(err => {
console.log(`error during signup of user: ${user.mobile})`);
return Rx.Observable.of(AuthResponse.FAILED_TO_SIGNUP);
})
.first();
}
如果您的signUp
函数没有订阅,您的代码就可以取消订阅,错误会在没有任何工作的情况下传播。这也是您的超时而不是您的超时的原因手机号码检查;你忘了传播错误。相反,您尝试从Rx.Observable.throw
回调中返回subscribeOnError
,该回调的签名为onError(error):void
一个好的做法是让你的Rx功能保持懒惰;只有在有人订阅时才执行代码。这有助于减少难以跟踪的错误。在您的情况下使用firebase.query()(返回一个promise),您可以使用.defer()
等待执行promise,直到有人订阅您的isUserExisting
函数。
public isUserExisting(mobile: string): Observable<boolean> {
if (!mobile) {
console.log("empty mobile");
return Observable.throw(new Error("Mobile number cannot be empty"));
}
return Rx.Observable.defer(() => firebase.query(() => { }, "/users",
{
singleEvent: true,
orderBy: {
type: firebase.QueryOrderByType.CHILD,
value: "mobile"
},
range: {
type: firebase.QueryRangeType.EQUAL_TO,
value: mobile
}
}
))
.do(firebaseResult => console.log('Checking for user success: ' + JSON.stringify(firebaseResult)))
.filter(firebaseResult => firebaseResult.value != null);
}
public saveUser(user: User) {
return Observable.defer(() => firebase.push('/users', user))
.do(result => console.log(`created user with key ${result.key}`))
}