angular - 只运行一次订阅

标签 angular typescript rxjs observable google-cloud-firestore

我只需要运行 userProfiles$.subscribe(async res => { 一次。但它可以无限运行。你能告诉我如何避免它吗?

这是 video of that issue :

.ts

async loginWithGoogle(): Promise<void> {
    try {
      const result = await this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
      const userId: string = result.additionalUserInfo.profile.id;
      const userProfile: AngularFirestoreDocument<UserProfile> = this.fireStore.doc(`userProfile/${userId}`);
      const userProfiles: AngularFirestoreCollection<UserProfile> = this.fireStore.collection('userProfile/', ref => ref.where('email', '==', result.additionalUserInfo.profile.email));
      const userProfiles$: Observable<UserProfile[]> = userProfiles.valueChanges();

      userProfiles$.subscribe(async res => { //problem is here
        if (res.length == 0) {
          await userProfile.set({
            id: userId,
            email: result.additionalUserInfo.profile.email,
            creationTime: moment().format(),
            lastSignInTime: moment().format()
          });
        } else {
          await userProfile.update({
            lastSignInTime: moment().format()
          });
        }
      });
    }
    catch (err) {
      console.log(err);
    }
  }

我已尝试将其转换为 promise,如下所示。但没有区别。也许我做错了?

 userProfiles$.map(async res => {
        if (res.length == 0) {
          await userProfile.set({
            id: userId, email: result.additionalUserInfo.profile.email,
            creationTime: moment().format(),
            lastSignInTime: moment().format()
          });
        }
      }).toPromise();

版本:

 "typescript": "2.4.2"
 "rxjs": "5.5.2",

最佳答案

promise 方式:

userProfiles$.toPromise().then((res) => {
   if (res.length == 0) {
      await userProfile.set({
         id: userId, email: result.additionalUserInfo.profile.email,
         creationTime: moment().format(),
         lastSignInTime: moment().format()
      });
   }
}).catch(err => {
   // handle error
});

首先,您将其转换为 promise,然后通过 .then() 方法收听它并等待已解决的 promise。

可观察的.take(1)

userProfiles$.take(1).subscribe(async res => { //problem is here
        if (res.length == 0) {
          await userProfile.set({
            id: userId,
            email: result.additionalUserInfo.profile.email,
            creationTime: moment().format(),
            lastSignInTime: moment().format()
          });
        } else {
          await userProfile.update({
            lastSignInTime: moment().format()
          });
        }
      });

注意 toPromise 方法不要忘记从 rxjs 运算符导入 toPromise 并且对于 take 你还应该导入 take 来自 rxjs 的方法

更新。 Angular 版本 >= 6

从 angular 6 开始,它需要 rxjs >= 6。现在像 take 这样的运算符现在可以导入并用在 .pipe() 方法中。 You can read more here

// somewhere at the top of file
import { take } from 'rxjs/operators';

userProfiles$.pipe(take(1)).subscribe(async res => { //problem is here
        if (res.length == 0) {
          await userProfile.set({
            id: userId,
            email: result.additionalUserInfo.profile.email,
            creationTime: moment().format(),
            lastSignInTime: moment().format()
          });
        } else {
          await userProfile.update({
            lastSignInTime: moment().format()
          });
        }
      });

关于angular - 只运行一次订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47718919/

相关文章:

angular - 如何通过 angular2 指令中的选项获取当前路线

javascript - Angular 2 : Mix Typescript, JavaScript 和 Dart

angular - 如何在页面重新加载时保留行为主题数据

javascript - RxJs:从 ID 标识的其他流更新列表中的值

typescript - angular2 CLI 项目中缺少一些 RxJS 运算符?该怎么办?

javascript - Firebase getDownloadURL() 不返回任何内容

javascript - 刷新页面时 firebase.auth().currentUser 返回 null

javascript - 在构造函数angular 2中声明属性

angular - 我怎样才能同时使用 : map & array in [ngClass] in angular 4?

angularjs - 如何在 TypeScript 中使用 ES6 模块语法导入 angular.IInjectorService