【问题标题】:firebase return onSnapshot promisefirebase 返回 onSnapshot 承诺
【发布时间】:2018-09-27 08:14:48
【问题描述】:

我正在使用 firebase/firestore,我正在寻找一种方法来返回快照的承诺。

onlineUsers(){
     // i want to return onSnapshot
    return this.status_database_ref.where('state','==','online').onSnapshot();
}

在我做的其他文件中

  componentDidMount(){
    // this.unsubscribe = this.ref.where('state','==','online').onSnapshot(this.onCollectionUpdate) 
    firebaseService.onlineUsers().then(e=>{
        console.log(e)
    })
}

我得到错误

错误:Query.onSnapshot 失败:使用无效参数调用。

TypeError: _firebaseService2.default.unsubscribe 不是函数

如果我这样做

onlineUsers(){
   return  this.status_database_ref.where('state','==','online').onSnapshot((querySnapshot)=>{
        return querySnapshot
    }) 
}

我明白了

TypeError: _firebaseService2.default.onlineUsers(...).then is not a function

此外, 当我这样做时

   this.unsubscribe = firebaseService.onlineUsers().then((querySnapshot)=>{
        console.log(querySnapshot.size)
        this.setState({count:querySnapshot.size})
    })

// 其他文件

 onlineUsers(callback) {
    return this.status_database_ref.where('state', '==', 'online').get()
}

它不听更改为 firebase,这意味着如果我更改 firebase,它不会更新或更改大小..

---- 火库功能 --- 我尝试制作每次更新 UserStatus 节点时触发的 firestore 功能,但这需要几秒钟,而且对我来说很慢。

module.exports.onUserStatusChanged = functions.database
.ref('/UserStatus/{uid}').onUpdate((change, context) => {
    // Get the data written to Realtime Database
    const eventStatus = change.after.val();

    // Then use other event data to create a reference to the
    // corresponding Firestore document.
    const userStatusFirestoreRef = firestore.doc(`UserStatus/${context.params.uid}`);


    // It is likely that the Realtime Database change that triggered
    // this event has already been overwritten by a fast change in
    // online / offline status, so we'll re-read the current data
    // and compare the timestamps.
    return change.after.ref.once("value").then((statusSnapshot) => {
        return statusSnapshot.val();
    }).then((status) => {
        console.log(status, eventStatus);
        // If the current timestamp for this data is newer than
        // the data that triggered this event, we exit this function.
        if (status.last_changed > eventStatus.last_changed) return status;

        // Otherwise, we convert the last_changed field to a Date
        eventStatus.last_changed = new Date(eventStatus.last_changed);

        // ... and write it to Firestore.
        //return userStatusFirestoreRef.set(eventStatus);
        return userStatusFirestoreRef.update(eventStatus);
    });
});

在线用户数计算和更新函数

module.exports.countOnlineUsers = functions.firestore.document('/UserStatus/{uid}').onWrite((change, context) => {

    const userOnlineCounterRef = firestore.doc('Counters/onlineUsersCounter');

    const docRef = firestore.collection('UserStatus').where('state', '==', 'online').get().then(e => {
        let count = e.size;
        return userOnlineCounterRef.update({ count })
    })
})

【问题讨论】:

    标签: javascript firebase callback google-cloud-firestore


    【解决方案1】:

    我知道为时已晚,但这是我使用 TypeScript 和 Javascript 的解决方案。

    打字稿

    const _db=firebase.firestore;
    const _collectionName="users";
    
        onDocumentChange = (
        document: string,
        callbackSuccess: (currentData: firebase.firestore.DocumentData, source?: string | 'Local' | 'Server') => void,
        callbackError?: (e: Error) => void,
        callbackCompletion?: () => void
    ) => {
        this._db.collection(this._collectionName).doc(document).onSnapshot(
            {
                // Listen for document metadata changes
                includeMetadataChanges: true
            },
            (doc) => {
                const source = doc.metadata.hasPendingWrites ? 'Local' : 'Server';
                callbackSuccess(doc.data(), source);
            },
            (error) => callbackError(error),
            () => callbackCompletion()
        );
    };
    

    JAVASCRIPT (ES5)

    var _this = this;
    onDocumentChange = function (document, callbackSuccess, callbackError, callbackCompletion) {
        _this._db.collection(_this._collectionName).doc(document).onSnapshot({
            // Listen for document metadata changes
            includeMetadataChanges: true
        }, function (doc) {
            var source = doc.metadata.hasPendingWrites ? 'Local' : 'Server';
            callbackSuccess(doc.data(), source);
        }, function (error) { return callbackError(error); }, function () { return callbackCompletion(); });
    };
    

    【讨论】:

    • 我希望我能提供 2 个赞成票:一个用于正确的解决方案,一个用于在 TypeScript 中提供解决方案!
    【解决方案2】:

    JavaScript 中的Promise 只能解析(或拒绝)一次。另一方面,onSnapshot 可以多次给出结果。这就是onSnapshot 不返回承诺的原因。

    在您当前的代码中,您留下了一个悬空的status_database_ref 侦听器。由于您不对数据做任何事情,因此继续监听它是一种浪费。

    而不是使用onSnapshotuse get

    onlineUsers(callback){
        this.status_database_ref.where('state','==','online').get((querySnapshot)=>{
            callback(querySnapshot.size)
        }) 
    }
    

    或者在你原来的方法中:

    onlineUsers(){
        return this.status_database_ref.where('state','==','online').get();
    }
    

    【讨论】:

    • 坦率地说,我编辑了我的帖子。我按照你的方式做了,它不听 Firestore 中的变化。如果我手动将状态更改为离线,我得到的大小不会改变,我确实看到它再次调用查询
    • 您问题中的代码和答案中的代码都不会监听更改。 onSnapshotget() 都将立即返回与查询匹配的当前文档。我现在在回答中给出的代码将显示哪些用户当前在线。在这一点上我不清楚你的代码试图完成什么(它开始感觉像XY problem)。
    • 我想听'status'集合。如果用户注册到firebase,它将uid的状态更改为“在线”,当他关闭应用程序时,它会更改为“离线”。我想获得在线用户的当前规模。如果应用程序中的用户和其他用户是关闭应用程序,那么它应该显示真实和更新计数
    • 嘿弗兰克,你有什么解决办法吗?
    • 您的查询运行良好,但是当我在应用程序上并且新用户更改为“在线”或“离线”时,计数器不会更改。计数器不再计算,它不听变化!此外,我编辑了我的帖子并使用了 firestore 功能,但更新它需要 3-5 秒,而且对我来说速度很慢
    【解决方案3】:

    我找到了办法

    onlineUsers(callback){
       return  this.status_database_ref.where('state','==','online').onSnapshot((querySnapshot)=>{
            callback(querySnapshot.size)
        }) 
    }
    
    componentDidMount(){
    
        this.unsubscribe = firebaseService.onlineUsers(this.onUpdateOnlineUsers);
        console.log(this.unsubscribe)
    }
    onUpdateOnlineUsers(count){
        this.setState({count})
    }
    componentWillUnmount(){
        this.unsubscribe();
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 1970-01-01
      • 2016-06-15
      • 2019-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多