Thanks to visit codestin.com
Credit goes to github.com

Skip to content

chore(observavles): Added ObservableMeteorSubscription and Observable…#362

Merged
Urigo merged 2 commits into
masterfrom
feature/observable-improvments
Jul 31, 2016
Merged

chore(observavles): Added ObservableMeteorSubscription and Observable…#362
Urigo merged 2 commits into
masterfrom
feature/observable-improvments

Conversation

@dotansimha
Copy link
Copy Markdown
Collaborator

@dotansimha dotansimha commented Jul 30, 2016

…Cursor with additional methods

@hongbo-miao @Urigo @kamilkisiela @barbatus

Changes made:

  • Added ObservableMeteorSubscription as return value for MeteorObservable.subscribe with API for stopping the subscription manually (.stop()).
    Example:
// Create new Observable
let observable = MeteorObservable.subscribe("myPub");

// Subscribe to the data (or use ngrx effects)
observable.subscribe(...);

// Stops the MeteorSubscription using the original Meteor's SubscriptionHandler
observable.stop();
  • Added ObservableCursor as return value for .find({}) with API for creating non-reactive Observable by using .nonReactive() and API for reloading non-reactive manually by using .reload().
    Example:
// Create non-reactive
let observable = MyCollection.find({}).nonReactive();

// Trigger Mongo Cursor fetch() and calls next() of the Subscription
observable.reload();

Both ObservableMeteorSubscription and ObservableCursor inherits from RxJS Observable so you can use it without any changes in your code.

@dotansimha
Copy link
Copy Markdown
Collaborator Author

@hongbo-miao I updated the example repo with an example for ubsubscribe from Meteor's subscription.

@Urigo Urigo merged commit 1c2dd58 into master Jul 31, 2016
@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Jul 31, 2016

Yeah, I am trying it! That is a smart way to handle unsubscribe Meteor.SubscriptionHandle!

@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Jul 31, 2016

@dotansimha PRODUCTS_COLLECTION_UPDATED was called 3 times now (because of 3 products), and those payloads are all same.

image

Think if we have 100 products, then it will run 100 times.

Need improve it to make it disptach PRODUCTS_COLLECTION_UPDATED only one time.

And when unsubscribe, it dispatch double times, which is 6 times.

@dotansimha dotansimha deleted the feature/observable-improvments branch August 1, 2016 18:25
@dotansimha
Copy link
Copy Markdown
Collaborator Author

dotansimha commented Aug 1, 2016

@hongbo-miao @Urigo
That's makes sense, because of Meteor's behavior of Mongo.Cursor's observe method, which exposes a callback for each event that can occur to the cursor (added, updated, removed).
Those callbacks are called each time there is a change in the Collection, and even if the DDP message contains multiple objects, the added callback will be called for each object.
You might also notice that even in the first time it fired (this first PRODUCTS_COLLECTION_UPDATED you see), you already have all 3 objects, because the fetch already got all the data from the message with all the objects, but it will still trigger the events for each object - and we can't detect that we already have all the objects.
A possible solution can be throttling of the events into batched call, for example, we can use lodash's throttle method and make sure that the next callback of the RxJS Observable called at most ONLY one time in each 100ms (100ms is just a random number I think that we need to test the range of the message to make sure we get the right timeframe).
This will make sure that in the first initialization of the Collection, you will get as minimum events as possible in the timeframe of 100ms (according to the example in the screenshot you provided, it will trigger the next only once). This solution will also solve the issue with unsubscribing to the Meteor publication, because that cause a deleted callback to be called multiple times (one for each object that deleted).
This solution might cause a delay in adding new object, update or remove single object during regular time (not the init or the unsubscribe), and I don't think that we can use throttle only in certain times, because we can't detect the state of the subscription (there it no connection between the Collection and the subscriptions of the specific Collection).

@dotansimha
Copy link
Copy Markdown
Collaborator Author

Actually, I think that it is better to use lodash's debounce instead of throttle (a great article about the difference can be found here), because we want to run the last time that added triggered, and not the first (because we want to make sure that we run it in the last time, because we can get multiple DDP message, and we want to call fetch only after the last message in the timeframe...

@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Aug 1, 2016

@dotansimha Oh, maybe we can use distinctUntilChanged only from RxJS5 ? Or debounceTime, or both?

this.streams
  .debounceTime(100)
  .distinctUntilChanged()
  .subscribe(x => {
});

@dotansimha
Copy link
Copy Markdown
Collaborator Author

Yeah that's sound good, but I think that it requires more that basic knowledge of RxJS... and I think that this is a problem that we need to solve in angular2-meteor, and provide a good solution for the users.

@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Aug 1, 2016

@dotansimha I feel in this case, distinctUntilChanged only is enough, no need for debounceTime. Maybe add distinctUntilChanged somehow inside of the API?

@dotansimha
Copy link
Copy Markdown
Collaborator Author

It crossed my mind, but I think that we need to prevent the call of fetch and not the Observable next.

@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Aug 1, 2016

@dotansimha DDP added should be and actually emit only once.

The second we may catch the ready event? (This second way I am not sure whether it is reliable, because I am afraid it may not emit this ready event)

image

@dotansimha
Copy link
Copy Markdown
Collaborator Author

The DDP message you are looking at are the subscription ready, which has nothing to do with the Collection events... the subscription events brings a chunk of objects and declare the "ready" event of the Meteor subscription, then the actual DDP message splitted into separate messages (one for each object), and then inserted into the Mongo Collection, then it call added for each new object in the collection...

@hongbo-miao
Copy link
Copy Markdown
Contributor

hongbo-miao commented Aug 1, 2016

Oh sorry, you mean Collection's added instead of DDP's added.. Got it!
Ok, so the problem is how to prevent unnecessary fetch.

@dotansimha
Copy link
Copy Markdown
Collaborator Author

Related: #363

@dotansimha dotansimha added this to the 0.6.3 milestone Aug 10, 2016
@dotansimha dotansimha self-assigned this Aug 10, 2016
@barbatus
Copy link
Copy Markdown
Collaborator

barbatus commented Aug 24, 2016

Hey, Dotan @dotansimha. I am making use of observables in MeteorComponent now, as a part of next version 0.7.0v. So I looked a bit closely into them, and have question. As I understand subscribe argument in Observable.create runs every time the user calls observable.subscribe. Which means
that assigning anything to observable instance itself like here (https://github.com/Urigo/angular2-meteor/blob/master/modules/minimongo-observable/meteor-observable.ts#L66) or https://github.com/Urigo/angular2-meteor/blob/master/modules/minimongo-observable/to-observable.ts#L18 doesn't have much sense since it's going to have a value assigned at the last subscribe call. So when one does stop here (https://github.com/Urigo/angular2-meteor/blob/master/modules/minimongo-observable/observable-subscription.ts#L15), it'll stop only the last subscription. Is it right, or is there anything that makes you think otherwise?

Also there seems to be an issue with the Mongo cursor's callbacks (see #358 (comment)). I think we'll need to change added to addedAt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants