javascript - 嵌套的可观察对象仅在超时后传播错误

标签 javascript angular rxjs observable

我的组件中有一个方法,它使用 observable 来监听第一个事件,并且超时时间为 15 秒。该方法调用一个嵌套的可观察量,如果参数为 null 或空,则该可观察量应抛出错误。我使用 Observable.throw() 但错误仅在超时/15 秒后传播。

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;
    }

更新: 保存用户()

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);
            })
        )
    }

最佳答案

创建自己的主题是一种不好的做法,您将在该主题上发出由内部订阅的可观察值发出的可观察值。这会导致内存泄漏,因为您无法取消内部订阅。

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 函数中的订阅,您的代码可以取消订阅,并且错误会在您这边不做任何工作的情况下传播。这也是您超时的原因而不是检查您的手机号码;您忘记传播错误。相反,您尝试从 subscribeOnError 回调中返回 Rx.Observable.throw,该回调的签名为 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}`))
}

关于javascript - 嵌套的可观察对象仅在超时后传播错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41519124/

相关文章:

javascript - 促进将标签属性附加到数组内、对象内的每个对象的最佳/最有效方法是什么?

javascript - 如何使用表格排序插件-Jquery 搜索表格中的项目

javascript - 使用闭包编译器正确键入实例变量

javascript - RXJS Observable 数组的简单过滤器

angular - RxJS - Subscriber 与 Observable 和 Subscription 有何不同?

node.js - 使用 rxjs ajax() 我得到 "CORS is not supported by your browser"

javascript - 无法使用 Node Express 中的 PUT 更新 mongo 中的名称

angular - 组件可注入(inject)?

javascript - 将日期从 JavaScript 转换为 Java

php - Laravel $request->all() 使用 multipart/form-data 为空