-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Feature Request: Map() or Extend function to FirebaseListObservable() for list items #848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@DennisSmolek I'm definitely interested! Are you up for doing some research with an experimental fork? |
Sure! |
I'd love to see if there's a way to measure the performance impact it has, so any metrics would be nice. |
@DennisSmolek I've created an issue (#883) for a proposal to address a problem that I have that's closely related to yours. Please check it out to make sure that I've understood what you've posted here and that the proposal will solve your issue as well as mine. |
@cartant I read over your issue, I haven't fully digested it but the point about performance I was making was in regards to digestion and subsequent change detection. Internally, this means if I have a heavy mapped function on a list of items, say to attach user data to a chat post, that request runs over data it's already done so to, as well as triggering basic change detection. By extending the ability to have a map function before adding to it's internal array it would let me make my own adjustments. I haven't had time to add this to the library yet as it's nuts here but something like this: function handleSnapMap(snap, mapFn?) {
let item = snap.val();
return mapFn ? mapFn(item) : item;
}
function makeListObs(path: string, mapFn?: any) {
return Observable.create(observer => {
let collection: Array<any> = [];
let ref = firebase.database().ref('/items');
// set array
ref.once('value').then(firstSnapshot => {
firstSnapshot.forEach(childSnap => {
collection.push(handleSnapMap(childSnap));
});
//fires once collection has loaded
observer.onNext(collection);
});
// listen for new, allow extension
ref.on('child_added', (singleSnapshot) => {
collection.push(handleSnapMap(singleSnapshot.val()));
observer.onNext(collection);
});
}); // obs
}// n |
@DennisSmolek Yeah, the expensive DOM updates for unchanged items are something I really want to avoid, too. PR #792 introduced a change to ensure that So, using your example, you'd do something like this:
The unwrapping and the mapping would be done in the one function. And if you need the original unwrap implementation, you could import |
And add a provider for the default unwrapSnapshot implementation. Closes angular#883 and angular#848.
And add a provider for the default unwrapSnapshot implementation. Closes angular#883 and angular#848.
And add a provider for the default unwrapSnapshot implementation. Closes angular#883 and angular#848.
And add a provider for the default unwrapSnapshot implementation. Closes angular#883 and angular#848.
I believe that what we are trying to implement here and in #888 / #883 is referred to throughout rxjs as a " Here is an example of how I have been using // ...
const childAdded = Observable.fromEventPattern(
(handler:QueryHandler) => { messagesQuery.on("child_added", handler) },
(handler:QueryHandler) => { messagesQuery.off("child_added", handler ) },
(snapshot:Snapshot): Message => unwrapSnapIntoMsg(snapshot) // <-- selector parameter
)
// ... ... I do this for As is shown in rxjs docs, As such, I recommend that when we do implement this feature, we call it " I also think that for consistency with rxjs api style, the selector should be the third parameter of this.af.database.list('/numbers',
{ preserveSnapshot: true, query: {} }, // <-- or `undefined`
(snapshot) => snapshot.val() * 10 // <-- third parameter in style of rxjs
); Thoughts? |
@somombo I can see what you mean, but my reservation is that selectors are usually passed the value that would otherwise be emitted by the observable. It seems a strange to have a selector that receives a snapshot when the observable would otherwise be emitting an unwrapped snapshot - for a |
@cartant Thanks for the timely feedback, I cant seem to think of an example of a selector that does not receive a value that would otherwise be emitted (e.g. like in our case, the selector does not receive the current list array even though that's what's ultimately emitted ... perhaps we may add this as an extra feature of our selector in case there are people that might use it? For now, not critical though). However, what I do have, is an example of a selector that receives a value that is otherwise not emitted (e.g. in our case, the selector receives wrapped/unwrapped snapshot yet the snapshot is merely a list-item of the Array that will ultimately emitted). Example of the latter, is resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any The There are many different types of selectors mentioned in the rxjs API e.g. Lastly, I do hear your concerns about how this issue currently affects change detection n' effeciency. I think this is a primary issue for me as well. I just wanted to make sure that we dont make it harder to streamline our public API towards consistency with rxjs in future, because of fear of breaking changes. |
@somombo Thanks for the examples. I agree that the Anyway, I'll wait until there is some action on the reviewing of the PR before considering or suggesting a rename, etc. Also, you might want to make any further comments against the PR itself, where they are more likely to be seen by a reviewer. |
I might be asking a question with an obvious answer, but what was the reason for introducing the FirebaseListObservable type in the first place? I might be just imagining things, but the last time I used firebase I had more methods available for the Observable type? Reading @DennisSmolek comment, am I wrong to assume that FirebaseListObservable uses the firebase once method internally and might not really be a pure Observable? |
@HoumanKml it is an observable but because you can no longer loop over |
@DennisSmolek That is interesting, I wasn't aware of that! It is just that it seems I can't use typical rxjx operators on the |
@HunderlineK
This is a bit buried in the Angular docs. I could only find it here: |
@DennisSmolek Would the new API with |
@davideast could you show an example snip of code that exemplifies how to achieve what was requested in this feature using the |
@davideast I think it will.. I'm still mulling over how I feel about the loss of $key but I think this issue specifically is resolved with |
Hey guys, I'm doing a few things with
FirebaseListObservables
that I'd like to be able to extend or map other things onto the items themselves but can't.consider:
You can't do this to the list object as it always returns an Array so you have to double wrap it:
The problem is that it has to run for EVERY item in the array and with more complex mapped functions this becomes a huge performance suck.
What would be cool is a way to do it like:
That only runs once as the item is actually changed/updated/whatever.
Now, I haven't spent a lot of time on this, but I think something like this would work:
Then modify either the
utils.unwrapMapFn
infirebase_list_factory
or just add it to theFirebaseListFactoryOps
class and modify thetoValue()
something like:
This way we can apply functions directly to the children as they get added to the inner array only once.
There are a million ways to do this I know, but I think it would be helpful in the main codebase somewhere...
The text was updated successfully, but these errors were encountered: