有没有更好的方法来链接.subscribe()调用?

时间:2019-08-10 07:53:49

标签: angular typescript

我有此代码:

this.categoriesSub = this.categoriesService.getCategories().subscribe(
      categories => {
        // This line is reached on the second run
        this.postsSub = this.postsService.getPosts().subscribe(
          posts => {
            // This line is NOT reached on the second run
            posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
            this.posts = posts;
          }
        );
      }
    );

在这里,我收到了一堆帖子,并且对于每篇帖子,我也都填充了category字段。

第一次加载该组件时效果很好,但是如果我导航到另一条路线,然后在浏览器中单击“后退”按钮以返回到该组件,它将不再获取帖子。

是否有更好的方法来链接.subscribe()通话?我已经看到了使用switchMap的示例,但是我不知道如何在这里实现。我已经尝试过像这样使用forkJoin

forkJoin(
      this.categoriesService.getCategories(),
      this.postsService.getPosts()
    ).subscribe(([categories, posts]) => console.log(categories));

...只是看我是否获得了数据,但它不起作用。

编辑:更准确地说:问题是在第二次运行时,未执行第二个.subscribe()调用的回调。没有错误,没有任何错误。看起来好像被跳过了。我在未执行的行上添加了注释。

稍后编辑:这是帖子服务:

export class PostsService {
  postsCollection: AngularFirestoreCollection<Post>;
  posts: Observable<Post[]>;

  constructor(private firestore: AngularFirestore) {
    this.postsCollection = this.firestore.collection('posts');

    this.posts = this.postsCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data() as Post;
        const id = a.payload.doc.id;
        return { id, ...data };
      }))
    );
  }

  getPosts(): Observable<Post[]> {
    return this.posts;
  }

  getPost(id: string): Observable<Post> {
    return this.posts.pipe(
      map(posts => posts.find(p => p.id === id))
    );
  }
}

在这里我在模板中使用this.posts

<app-post-item *ngFor="let post of posts" [post]="post"></app-post-item>

帖子内容:

<div class="post-item" @fade>
    <span class="badge post-category">{{ post.category.name }}</span>
    <a [routerLink]="['./', post.id]" class="post-title text-strong">{{ post.title }}</a>
    <span class="post-date text-medium">{{ post.date.seconds * 1000 | date }}</span><br>
    <img *ngIf="post.coverUrl" class="post-cover-img" src="{{ post.coverUrl }}" alt="none">
    <p class="post-body">{{ postBody }}</p>

    <div class="actions">
        <a [routerLink]="['./', post.id]" class="read-more-button strong">Read More!</a>
    </div>
</div>

2 个答案:

答案 0 :(得分:2)

forkJoin仅在完成所有可观察项时发射。尝试改用zip。但是您需要确保两个可观察对象都发出值或错误。如果getCategoriesgetPosts是网络请求,则zip优于switchMap,因为这些请求将并行执行。

zip(
  this.categoriesService.getCategories(),
  this.postsService.getPosts()
).subscribe(([categories, posts]) => {
    posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
});

问题的根源是您的服务共享了are hot by design的AngularFire可观察对象。 getPosts()getCategories()方法应该创建新的可观察对象,例如:

export class PostsService {
  postsCollection: AngularFirestoreCollection<Post>;

  constructor(private firestore: AngularFirestore) {
    this.postsCollection = this.firestore.collection('posts');
  }

  getPosts(): Observable<Post[]> {
    return this.postsCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data() as Post;
        const id = a.payload.doc.id;
        return { id, ...data };
      }))
    );
  }
}

此外,您不应直接使用Subscribe / Unsubscribe Observable方法。忘记退订很容易。改用async管道,该管道在组件销毁时会自动取消订阅。

@Component({
  template: `<app-post-item *ngFor="let post of posts$ | async [post]="post"></app-post-item>`,
})
class MyComponent {
  readonly posts$: Observable<Post[]>;

  constructor(
    postsService: PostsService,
    categoriesService: CategoriesService
  ) {
    this.posts$ = zip(
      categoriesService.getCategories(),
      postsService.getPosts()
    ).pipe(
      map(([categories, posts]) => {
      posts.forEach(p => p.category = categories.find(c => c.id === p.categoryId));
      return posts;
    }));
  }
}

答案 1 :(得分:0)

问题是我再次订阅了另一个组件中的{ dependencies: { expo: "^34.0.1", react: "16.8.3", "react-dom": "^16.8.6", "react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz", "react-native-gesture-handler": "^1.3.0", "react-native-web": "^0.11.4", "react-navigation": "^3.11.1" }, devDependencies: { "@types/react": "^16.8.23", "@types/react-native": "^0.57.65", "babel-preset-expo": "^6.0.0", typescript: "^3.4.5" } } ,但是没有在Select p.Id, max(p.author) author, max(p.community) community, max(p.created) created ,max(p.title) title , max(p.content) content ,GROUP_CONCAT(DISTINCT (cttc.category)) category , GROUP_CONCAT(DISTINCT (ctatc.name)) Tag From Post p inner Join Communnity c On c.Id = p.CommId right Join ( Select cc.Community, tc.category, tc.Id From TagCategory tc inner join CommunnityTagCategories cc ON cc.Category = tc.Id) cttc ON p.Commid = cttc.Community Left join ( Select p.post,t.name,ct.category From PostTags p inner join Tag t ON t.Id = p.Tag inner join TagCategorised ct ON ct.Tag = t.Id ) ctatc ON ctatc.category = cttc.id and ctatc.post = p.id GROUP BY p.Id; 方法中调用postsService

这就是为什么只有该呼叫无法正常工作的原因。