过滤数组的可观察量(Observable <event []>)

时间:2017-08-31 06:22:03

标签: angular firebase-realtime-database rxjs observable angularfire2

以下是我的情景:

  1. 我在不同地点发生了1000次事件(Firebase对象)。
  2. 我需要根据用户的位置偏好向用户显示活动列表。
  3. 有些用户可能对来自所有15个地点的活动感兴趣,而某些用户可能只在一个地点(15个不同地点)的活动中进行了交叉。
  4. 此外,我只需要显示即将发生的事件,而不是过去的事件(由时间戳属性endDateLong确定)
  5. 因此,我使用angualarFire orderByChild
  6. 在本地应用位置过滤器逻辑和时间过滤器逻辑
  7. 在任何时候,只向用户显示30个即时事件就足够了,即使这些事件已经定位到所有位置并且他们应该获得所有1000个事件。
  8. 我的解决方案(设计):

    1. 我不想获取所有1000个事件并过滤它们
    2. 相反,我只是想取一个小块(比方说50)用用户的位置偏好来过滤它。
    3. 如果我在应用过滤器之后得到30多个事件并且很好。我们可以在UI中显示相同内容。
    4. 但是如果过滤器将50减少到10个事件,我会再次递归调用我的函数以获得50个事件的下一组(基于endDateLong)。
    5. 我重复第4点,直到我得到30多个事件或直到Firebase中的整个数组都用完为止。
    6. 我的工作代码:

      1. 这种递归函数运行良好且很好,并且可以达到目的。

        fetchFilteredEvents(startKey:number) {
        
        let self                =   this;
        let cacheKey            =   this.fireRoute.getPathForMetaEvents();
        let evListObs:FirebaseListObservable<Event[]>;
        
        evListObs               =   self.db.list(cacheKey, {
            query               :   {   
                orderByChild    :   'endDateLong',
                startAt         :   startKey,
                limitToFirst    :   50  
            }   
        }); 
        
        return evListObs.first().map(evList => {
            let cList           =   evList.filter(ev => {
        
                /** 
                 * BEGIN: Check if event falls in any Preferred locations
                 */
                let allBlocks   =   self.volService.me.locationPreferences.blocks;
                let prefBlockIDs=   Object.keys(allBlocks)
                                        .filter(b => { return allBlocks[b] }); 
                let matchingObj =   prefBlockIDs.find( bid => { return bid == ev.block.id } );
        
                // return true, if any matching block is found
                if (matchingObj)    return true;
                /** 
                 * END: Check if event falls in any Preferred locations
                 */
        
                return false;
            }); 
        
            self.eventCount     +=  cList.length;
        
            // If required 30 items are retrieved or event list is exhausted just return current list.
            // If not, recursively call the function again with timestampe of the last event and append it's return value to current array and return the whole appended list
            if (evList.length == 1 || self.eventCount > 30) {
                return cList;
            } else {
                let lastEvent   =   evList[evList.length -1];
        
                console.log("Fetch next page @ ", lastEvent.endDate);
                console.log("Current list is ", cList);
                return self.fetchFilteredEvents(lastEvent.endDateLong).then(allEvents => {
                    return allEvents.concat(cList);
                }); 
            }   
        
        }).toPromise();
        
        }   
        
      2. 此代码出现问题:

        1. 我们假设用户只选择一个地点的活动。
        2. 这意味着许多被抓取的事件将被过滤掉,并且在我收到30个事件之前会发生几次递归。
        3. 需要几秒钟才会更新UI,直到获取30个事件或列表用完为止。
        4. 整个功能阻止了UI更新。
        5. 我想要的: 我想通过observables以某种方式改进代码:

          1. 所以我可以返回我的部分事件数组并填充UI
          2. 超过第1点,我渴望学习Observables足以处理这种情况: - )
          3. PS:它的Angular 2(或4)代码和AngularFire2

            任何指针?

            更新1 - 转换为Observables(没什么)

            private fetchFilteredEvents(startKey:number) : Observable<Event[]> {
            
                let that                =   this;
                let cacheKey            =   this.fireRoute.getPathForMetaEvents();
            
                let evObs               =   that.db.list(cacheKey, {
                    query               :   {   
                        orderByChild    :   'endDateLong',
                        startAt         :   startKey,
                        limitToFirst    :   10  
                    }
                }).map(evList => {
                    let cList           =   evList.filter(ev => {
                        // Filter logic goes here
                    });
            
                    that.eventCount     +=  cList.length;
            
                    // If required 30 items are retrieved or event list is exhausted just return current list.
                    // If not, recursively call the function again with timestampe of the last event and append it's return value to current array and return the whole appended list
                    if (evList.length == 1 || that.eventCount > 30) {
                        return cList;
                    } else {
                        let lastEvent   =   evList[evList.length -1];
            
                        console.log("Fetch next page @ ", lastEvent.endDate);
                        console.log("Current list is ", cList);
            
                        // THIS IS NOT WORKING. I am only getting the first 10 events. I think I should somehow merge the returning obserable of recursive calls to `that.fetchFilteredEvents()` to `evObs`, rather than array merging as done here.
                        return that.fetchFilteredEvents(lastEvent.endDateLong).subscribe(nextList => {
                            console.log(nextList);
                            cList   =   cList.concat(nextList);
                            return cList;
                        });
                    }
            
                });
            
                this.currentList = evObs;
                return this.currentList;
            

0 个答案:

没有答案