简体   繁体   中英

Javascript Observable performance issue

Current Working Code

I have the following rxjs/Observable :

findMessages(chatItem: any): Observable<any[]> {
    return Observable.create((observer) => {
        let processing: boolean = false;
        this.firebaseDataService.findMessages(chatItem).forEach(firebaseItems => {
            if (!processing) {
                processing = true;
                this.localDataService.findMessages(chatItem).then((localItems: any[]) => {
                    let mergedItems: any[] = this.arrayUnique(firebaseItems.concat(localItems), false);
                    mergedItems.sort((a, b) => {
                        return parseFloat(a.negativtimestamp) - parseFloat(b.negativtimestamp);
                    });
                    if (this.me && mergedItems && mergedItems[0] && this.me.uid === mergedItems[0].memberId2) {
                        this.updateChatWithMessage(chatItem, mergedItems[0], false);
                    }
                    observer.next(mergedItems);
                    processing = false;
                });
            }
        });
    });
}

and

this.firelist = this.dataService.findMessages(this.chatItem);
this.firelist.subscribe(items => {
    ...
});

As you can see, it returns a list of firebaseItems and localItems , which are merged to mergedItems . This works perfectly.

Performance Enhancement

However, I am trying to increase the performance that the items load. So figure, I would like to first load the localItems , and then add to the list with the firebaseItems .

So I try add the following function:

findLocalMessages(chatItem: any): Observable<any[]> {
    return Observable.create((observer) => {
        this.localDataService.findMessages(chatItem).then((localItems: any[]) => {
            localItems.sort((a, b) => {
                return parseFloat(a.negativtimestamp) - parseFloat(b.negativtimestamp);
            });
            observer.next(localItems);
        });
    });
}

and call it as follows:

this.firelist = this.dataService.findLocalMessages(this.chatItem);
this.firelist = this.dataService.findMessages(this.chatItem);
this.firelist.subscribe(items => {
    ...
});

Problem

This has now introduced a bug, that there are now 2 Observables and the results are not as expected. The sort order is incorrect, and some of the items are not being added to the this.firelist for some reason.

Question

Whats the best way to handle this?

I was thinking if it's possible to make the findLocalMessages Observable only get fired once, and then it never works again, as the findMessages Observable will maintain the list. Is this possible? I have been looking at the Observable api, and can't seem to figure out how to do that.

Any help appreciated.

With the risk of oversimplifying the problem statement, you have two streams of data that you want to merge and sort in an efficient manner.

The separation you have made is a step in the right direction. The reason why you are not getting all the messages is that you are overriding the first observable with the second.Have a look at the following example and see what happens if you try and assign the second observable to move instead of move2.

  let move = Observable.fromEvent(document.getElementById("1"), 'mousemove'); let move2 = Observable.fromEvent(document.getElementById("2"), 'mousemove'); move .subscribe((event:any) => { if (event) { console.log(event.path[0].id) } }); move2 .subscribe((event:any) => { if (event) { console.log(event.path[0].id) } }); 
 <h1> <div id="1"> aaaaaaaaaaaaaaaaaaaaaaaaa </div> <div id="2"> bbbbbbbbbbbbbbbbbbbbbbbbb </div> </h1> 

In order to merge the two streams together properly you need to use the merge operator as shown below:

 let move = Observable.fromEvent(document.getElementById("1"), 'mousemove'); let move2 = Observable.fromEvent(document.getElementById("2"), 'mousemove'); move.merge(move2) .subscribe((event:any) => { if (event) { console.log(event.path[0].id) } }); 

Now all you need to do is sort them. I would advice that you do the sort only after the merge because otherwise, you will end up with two streams that are sorted locally, not globally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM