Making tracker work with async code

On our way to a fibers-free meteor, we are making packages, and core pieces accept async code.
Our Tracker is one of them that impacts many Front-end frameworks like Blaze and React. Thanks to @radekmie we have a draft that we may need to discuss in the community. Check his PR here.

In summary, for those who do not want to go to GitHub quoting @radekmie:

I implemented a way to make Tracker.autorun work with async operations without any additional API surface, Zone.js, and any other magic at a cost of… Well, using generators.

I think it can be rather useful for the future but I would like to make a babel plugin or something with reify in order to hide using generators and documents its limitations once that many reactivity trackers do not handle well having async code

What do you think of this implementation?
share them below.

5 Likes

It’s badly needed to make the babel/reify plugin work. As one of the benefits of moving away from fibers is aligning meteor to how developers expect javascript to work. Introducing this new way of doing things again seem against this direction

3 Likes

I think we must also consider the current limitations of V8 and the impossibility of tracking native promises (async/await) to obtain context in async calls. Unless we upset the reactivity model with other patterns (e.g. observe), the proposal to use generators for only the autorun part seems to me to be worth considering. From my point of view, considering that it is a stretch to make minimongo work in asynchronous mode, it would be a case of also being able to have mongo methods in the synchronous version and keeping asynchronous only for isomorphic code. As far as I know, even angular, which uses zone.js, requires code translation to decode async/await.

This thread seems similar to Tracker and async mongo methods? Let us keep just one of the two thread, so as not to disperse the considerations.

Have given some thought if I would need to rewrite the structure of all my angular code to match an async API, but after some thought I realize that it will not be necessary.

I have a situation where I for instance loop over the result of some reactive collection helper.
i.e. <div ng-repeat="object in myDoc.getObjectsFromMiniMongo()>

if getObjectsFromMiniMongo returns a Promise<Array> it will not be iterable. I can however write a generic wrapper, that takes an object and wraps all it functions in a function that returns a default value = undefined until the promise is resolved when it can tell angular to rerender and then returning the final value and calling Tracker.changed. Thus, it will depromisify it, and thereby stopping async “pollution”.

Probably something similar could be done for other frameworks, converting async interfaces to sync but reactive ones.