如何在服务中创建一个方法来返回 onSnapshot 的结果,然后在我的组件或 Ionic 页面中使用它?

Posted

技术标签:

【中文标题】如何在服务中创建一个方法来返回 onSnapshot 的结果,然后在我的组件或 Ionic 页面中使用它?【英文标题】:How can I create a method in a service that returns the result of onSnapshot and then using it in my Component or Ionic Page? 【发布时间】:2018-04-13 06:38:42 【问题描述】:

我正在使用“ionic-angular”:“3.7.1”和 Firebase Cloud Firestore。我希望每次更新、删除或添加所有文档时都将它们放入 Post 集合中。我知道调用onSnapshot方法我可以得到它所以我在服务中定义了这个方法。

getPosts(token: string)
  const userId = this.authService.getActiveUser().uid;
  let posts = [];
  return firebase.firestore().collection("Post").onSnapshot(function(querySnapshot) 
      querySnapshot.forEach(function(doc) 
          posts.push(doc.data());
        );
        console.log("Posts: ", posts.join(", "));
        return posts;
      );

所以在控制台中,我可以看到数组 Posts 中的所有帖子,但是如果在我的组件中使用 this.post.getPosts(token) 调用此方法,我会在控制台中得到以下输出:

ƒ () 
  asyncObserver.mute();
  firestoreClient.unlisten(internalListener);

那么,

文档

https://firebase.google.com/docs/reference/js/firebase.firestore.Query?hl=es-419

https://firebase.google.com/docs/firestore/query-data/listen?hl=es-419

【问题讨论】:

【参考方案1】:

你可以这样实现它:

从你的服务返回一个 Observable:

getPosts(token: string) 
  const userId = this.authService.getActiveUser().uid;
  let posts = [];
  return new Observable(observer => 
    const unsubscribe = firebase.firestore().collection("Post").onSnapshot(querySnapshot => 
      querySnapshot.forEach(function(doc) 
        posts.push(doc.data());
      );

        observer.next(posts);
      );

    return () => 
      unsubscribe();
    ;
  );

然后在您的组件或离子页面:

const _this = this; // 'this' inside 'subscribe' refers to the observable object
this.postsObserver = this.branchService.getPosts(token);
this.postsObserver
  .subscribe(
    next(posts) 
      _this.posts = posts;
    ,
    error(error)  console.log(error); , // optional
  );

每次您更改任何帖子时,该更改都会反映在列表中,而您无需再次致电 getPosts

注意

另外,如果您的服务是 posts 独有的(我推荐),我建议您在初始化服务时保留对 posts 集合的单一引用:

  this.postsRef = firebase.firestore().collection('Post');

firebase.firestore().collection('Post') 不计入您的数据库配额,但在对所述集合的所有其他后续查询中使用this.postsRef 来保持代码看起来更干净并没有什么坏处。

编辑

添加了在 Observable 被销毁时调用的“teardown”函数。在这种情况下,当我们销毁 Observable 时,我们会阻止 firebase 实时监听器监听更多更新。为您的客户释放更多带宽。

参考资料:

Angular doc Firebase doc Learning Observables

【讨论】:

【参考方案2】:

更新:

如果您需要了解如何使用Firestore 实现通用service/provider,请参阅this artcile

旧反馈:

你需要在这里使用胖箭头函数,你在这里犯了很多错误。你可以试试下面code

  getPosts(token: string)
    const userId = this.authService.getActiveUser().uid;
    let posts = [];

     retrun firebase.firestore().collection("Post").get().then((querySnapshot)=> 
     
       querySnapshot.forEach((doc)=> 
           posts.push(doc.data());
      );
        return posts;
     );
 

Doc

【讨论】:

嗨 Sampath 使用胖箭头函数并不能解决问题,箭头函数是另一种编写匿名函数的方法,所以我通过这个更改得到完全相同的结果。嗨 Sampath 不能解决问题,箭头函数是另一种编写匿名函数的方式。 您必须始终在 TS 中使用箭头函数。否则,您将面临很多local/global scope 问题。 查看最新更新。 现在我得到 __zone_symbol__state: null, __zone_symbol__value: Array(0) if a print console.log(this.post.getPosts(token)) 当我调用该方法时。据我了解,get 方法只获取一次值,而不是在文档更改时获取值。 通过这个更新,我可以编写一个Async 调用并重用我的代码,但get() 不会监听 de collection,因此它只获取一次文档,而不是当它们为此目的而更改时使用ononSnapshot()

以上是关于如何在服务中创建一个方法来返回 onSnapshot 的结果,然后在我的组件或 Ionic 页面中使用它?的主要内容,如果未能解决你的问题,请参考以下文章

如何在卵石手表中创建表格

如何在 ASP .Net (Aspx) 中创建要从 Javascript 访问的 Web 服务方法?

如何在Flutter(2021)中创建过滤器搜索列表视图

如何在 SwiftUI 中创建一个获取 View 并返回自定义结果的函数?

如何在 C++ 中创建一个公开返回对象的函数的 COM Dll?

如何使用当前日期在 FTP 服务器中创建目录(文件夹)?