When to use the promise returned by ractive.set? - ractivejs

The ractive.set method returns a promise. When performing a simple set operation (single value or map) and then immediately referencing the new value via ractive.get, is it recommended to use the promise? Or is that completely unnecessary?
I've been avoiding the promise and found that I don't need it, but maybe I've just been lucky so far. Here's an example of what I mean:
ractive.set("foo", "bar");
console.log(ractive.get("foo")); // always outputs the correct value "bar"
I'm worried that the set operation is asynchronous and this will become evident on slower machines or if I start using the more advanced features of Ractive.
According to the Ractive docs:
[ractive.set] Returns a Promise that will be called after the set
operation and any transitions are complete.
Based on that, I wonder if the promise is really meant for post-transition work.

Based on that, I wonder if the promise is really meant for
post-transition work.
Exactly. The value update (and the resulting DOM changes per the template) happen synchronously, the promise is meant for asynchronous response to end of transitions.
This is also why the set operation also has a hash map option for the input parameters so multiple sets will be batched in one go:
ractive.set({
foo: 'foo',
bar: 'bar'
}).then( () => {
// this happens asynchronously ***after*** code execution has
// continued below on next event cycle or after transitions complete
});
// data and DOM have been updated as the code continues synchronously here:
console.log( ractive.get() );

Related

Is a method still "pure" if it invokes a designated callback given as parameter

Eg. PureFoo(onSuccess: () => { DoSomething(); }); (example in C#)
Does Purefoo still counts as pure (without "side effects") if it invokes onSuccess? or is the method only "honest" (as in doesn't hide what it does)?
I've searched on Google but it didn't yield relevant results.
So, long story short, that sounds like a no.
If there are side effects, from whichever source, it shouldn't/can't be called pure.
However, I guess it can still be made more honest by limiting the side effects to only all clear & explicit intended callbacks which sorta ask as an alternative return + call based on returned values.
Note that you can't ensure the callback is called only when expected and the number of times it's expected, etc. still.
In this particular case, onSuccess has a name and a signature (returning void/unit) that signals an intentional side effect. If your function doesn't do anything with the result of the onSuccess() call, then there isn't anything possible to pass into there that will make the outer call pure.

Why is my Observable emitting more values than expected, and why is auditTime a fix?

I asked a question here recently about observables and you guys were of really great help (as always). Now I'm having a similar situation, and me and my team-mate are bending our brains over it.
The bug to fix was: user sees a collection of assets, and on browser refresh the wrong set of assets was being loaded. It turns out the key to the problem was one particular pipe observing the currently selected collection. Here's the relevant code:
this.selectedCollection.pipe(
filter((v) => !!v)).subscribe((v) => {
console.log('PIPE: selected collection', v.collectionId);
this.store.dispatch(
// action jackson on redux
)
);
});
The action to be dispatched here is for loading the assets of the collection. One collection was always loaded first as default and it was conflicting with further selections made by the user.
I've also added console.logs on the relevant reducers and effect to visualize behavior.
What happens on browser refresh is this:
Collection 9-em... is the default collection we don't want to see, and collection 9uem... is the user's choice whose asset's we want to see.
The first five lines show the expected output of the observable:
default collection set as selected collection
reducer 'is loading' assets
the user triggers a change selected collection action
the selected collection value is being updated and emitted accordingly
Now we would have expected the effect to load the assets and that's it. But what happens is that the pipe keeps emitting the same values once again, which is weird, because I'm 100% sure no further value is being set from anywhere. But it would also be fine, since we end up with the desired value. Yet strangely, the reducer is handling the load actions in reverse order, which led to the wrong assets being loaded (this could be a whole different issue on top).
Adding auditTime(200) as first operator to the pipe above fixed the issue. No further values were emitted.
Now, my questions are:
Why are the values emitted twice? Could it be an inappropriate operator/subscription some place else (didn't see anything suspicious)?
And why is auditTime(200) magically fixing this?
The effect also works as a pipe of actions being filtered, and it contains an auditTime(200) operator before executing, so that it executes only on the last action. While I do understand on principle what it does, I'm not quite sure if using auditTime like that just because it works is such a good idea.
I assume this is an issue out of noob confusion resulting in using rxjs not the right way. Unfortunately, I couldn't find anything useful on google. I really don't like 'fixing' a bug by adding a line of code that I just don't understand.
Thank you so much in advance!
As requested by fridoo, here's the code for this.selectedCollection:
get selectedCollection(): Observable<collectionState.CollectionsData> {
return this.store
.select(collectionState.getSelectedCollection)
.pipe(distinctUntilChanged());
}
And for getSelectedCollection:
export const getSelectedCollection: (state: any) => CollectionsData = (state: any) =>
getCollectionsState(state)
? getCollectionsState(state).selectedCollection
: undefined;
The rest is pretty forward just objects of state, the observable created via the select method. We're not using any library for redux (not my decision), so select is implemented like this:
select<T>(fn: (state: any) => T): Observable<T> {
return this.state$.pipe(map(fn), distinctUntilChanged());
}
Does this help any further?

Can I return an async value (a Promise) from a Meteor helper?

A Promise is an object type which serves as a placeholder for a future result,
such as the body of an HTTP request, or the return value of a Meteor method call.
Basically any function that forces you to pass a callback to recieve its
return value (instead of just returning it) is said to be an async function,
and the value it gives back can be represented by a Promise.
The issue in Meteor is that helper methods are only intended to work with
synchronous values - such as the text in a web page, or the contents of a
Minimongo collection. When you return a Promise from one, the helper
shows [object Promise] instead of the resolved value
does not update when the promise resolves
Some attempts at solving this exist: simple:reactive-method
and arsnebula:reactive-promise, but they require you to change your helpers to a certain style, or only work with Meteor.call instead of just simply allowing a generic promise to be returned.
Is there something existing I've overlooked, or is there a solution in the works? I've been experimenting with this for some time, and may work on something myself if there's not an official answer.
Even with respect to other libraries out there, I think the answer for now is to go with the package deanius:promise (disclaimer: I authored it, with input from the authors of some other packages).
It does what the question asks, and adds some nice touches like controllable error and loading messages.

Meteor subscribe onReady() and observe() added double counted

I want to wait for all data to be downloaded from the subscription and then create map markers for them all at once at the beginning. To do this, I have a session variable set to false. Then when onReady calls, I initialize all the markers. Then I set the session variable true indicating that the first delivery is in and initialized. In my observe callback, I check the session variable and so long as its false, I dont add any markers. Then, if its true, I will add markers -- assuming non of these markers are already initialized. Sometimes, however, I get a double-count and create twice as many markers.
I guess a good first question to ask is what the relationship is between onReady and observe added? Its not terribly clear in the docs. Is this even the correct way of doing things -- creating a session variable to suppress the observe added function until onReady is done? I dont think so. Also note that the double count doesnt happen every time so its a timing thing... kind of annoying.
Thanks
Yes this is the behavior with observe(). When you run observe initially it will have an initial query that will match everything and run into added.
It is also present when onReady hasn't yet fired but the collections are empty at that point so the initial ones aren't visible. This is mentioned in the docs
Before observe returns, added (or addedAt) will be called zero or more times to deliver the initial results of the query.
I'm not sure entirely how to avoid the initial items. I have done something like this in the past:
var QueryHandle = Collection.find().observe({
added: function() {
if(!QueryHandle) return false;
});
I know this works on the server but I'm not certain if it does on the client.
Another solution would be to run the handle before onReady is called and only stop returning if the subscription is complete: i.e
Meteor.subscribe("collection", function() {
subscribed = true;
});
var QueryHandle = Collection.find().observe({
added: function() {
if(!subscribed) return false;
}
);
Be careful not to run this in a Deps.autorun because then it would be run again if the .find() query params are reactive.
This might happen sometimes depending on how fast the server response. If you use Session it becomes a reactive hash so if it happens fast enough that subscribed returns true. Try using an ordinary variable instead.
If its not helpful there might be an alternative way to avoid the initial ones and a deeper level but it might take a dig into the livedata package.

Firebase in node.js, set() callback is delayed

I have an EC2 instance running a small node script connecting to Firebase. Strangely enough, it happens quite often on a small instance that the set operation gets executed immeditely but the callback function only gets called much later (between 30s to 2 minutes). Do you see any reason why it would happen that way?
console.log('creating');
// Create workspace
rootRef.child('spaces').child(chid).set(req.space, function(error) {
var end = new Date().getTime();
var time = end - start;
console.log('- created', error, time);
});
The bug is directly related to node 0.11 (set() callback is only called the first name in my scenario). Just revert to 0.10.x and it's all fixed!
I've been facing the same issue. the "Set" callback is not being invoked at all. I noticed, however, that if I run a snippet code similar to yours in a standalone file, the callback is invoked very quickly.
It turned out that if you're installing listeners on the same Node you're calling the "set" function on (i.e., on('child_added'), on('child_removed') ... etc) and that Node has a huge number of records, it'll simply take ages.
I removed the listeners ( to test) and the "set" started to invoke the callback very quickly.
I hope this helps!

Resources