-
-
Notifications
You must be signed in to change notification settings - Fork 115
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
Handle async code #364
Comments
Agreed! |
OK, I think this is something that we should include as a main feature in Blaze 2.7. |
Maybe we can first collect what all needs to be supported, especially in combination with all new changes by Meteor 2.8+ |
Regarding asynchronous management, I think it is also useful to consider hooks: created, rendered and destroyed. Now callbacks are synchronous but we will often have asynchronous calls within them. |
FYI: I tried implementing the Tracker context logic, currentComputation, with zone.js but it doesn't not intercept the native promises (async/await). Used with legacy version of the bundle it works but feels like going backwards. Does anyone know of alternative packages to do this? |
My point of view regarding handling async code would be divided in two parts. Not sure if it makes 100% sense but it could be a way to implement this. {#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await} in blaze could be like: <template name="example">
{{#with asyncTest}}
{{#await this.foo}}
<p>...waiting</p>
{{:then bar}}
<p>result: {bar}</p>
{{:catch error}}
<p style="color: red">{error.message}</p>
{{/await }}
{{/with}}
</template> Then or in parallel, we would need to handle how to make |
The idea is not bad, but Tracker has to support asynchronous processes and to do that I think it will have to track calls, a bit like Angular and Dart. Your Blaze example can already be done with reactive variables and a heavy memory overhead, but if we have no way to intercept changes to an asynchronous object we lose reactivity. Assume the following pseudo-example
Changes coming from the DDP are not intercepted because on the first await the autorun loses context. Losing the native Meteor reactivity has a big impact. My opinion is to keep Minimongo client-side synchronous at least until the Tracker problem is solved. |
The concept of synchronous Minimongo access is something I suggested also in the main Meteor Async PR discussion: async focus can go first to Meteor.call use cases. It would reduce impact to smaller set of Tracker async cases one has to deal with. |
@klablink I observed this (indirectly) by turning a helper into an async helper, can you elaborate why the context is lost after the first await ?
Agreed ! |
Hi @polygonwood Blaze's reactivity is based on Meteor's Tracker package. This uses a global variable, currentComputation, to map the relationship between a function to be called when a certain reactive variable changes and/or a minimon search. Now, if the process becomes asynchronous, on the first await the currentComputation will lose the reference for the rest of the calls. For better understanding I will insert the code extract of Current Tracker: _compute() {
this.invalidated = false;
var previous = Tracker.currentComputation;
setCurrentComputation(this);
var previousInCompute = inCompute;
inCompute = true;
try {
withNoYieldsAllowed(this._func)(this);
} finally {
setCurrentComputation(previous);
inCompute = previousInCompute;
}
} As you can see, There has been much discussion on the subject (see this PR), and it seems that in Meteor version 2.10 there will be the possibility of invoking asynchronous functions by passing the tracker context. This will mean a major change for Blaze and many client packages. |
@klablink
thanks for the clarification and the pointer to the PR
…On Mon, Jan 9, 2023 at 8:59 AM klablink ***@***.***> wrote:
@klablink <https://github.com/klablink> I observed this (indirectly) by
turning a helper into an async helper, can you elaborate why the context is
lost after the first await?
Hi @polygonwood <https://github.com/polygonwood>
Blaze's reactivity is based on Meteor's Tracker package. This uses a
global variable, currentComputation, to map the relationship between a
function to be called when a certain reactive variable changes and/or a
minimon search. Now, if the process becomes asynchronous, on the first
await the currentComputation will lose the reference for the rest of the
calls.
For better understanding I will insert the code extract of Current Tracker:
_compute() {
this.invalidated = false;
var previous = Tracker.currentComputation;
setCurrentComputation(this);
var previousInCompute = inCompute;
inCompute = true;
try {
withNoYieldsAllowed(this._func)(this);
} finally {
setCurrentComputation(previous);
inCompute = previousInCompute;
}
}
As you can see, this._func must be synchronous to work in the current
context, otherwise setCurrentComputation(previous) is executed
immediately, losing context.
There has been much discussion on the subject (see this PR
<meteor/meteor#12294>), and it seems that in
Meteor version 2.10 there will be the possibility of invoking asynchronous
functions by passing the tracker context. This will mean a major change for
Blaze and many client packages.
—
Reply to this email directly, view it on GitHub
<#364 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AMTJC22FOWAUNR67PE4P56LWRPAOXANCNFSM5R2FQQQA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Hello from Germany 😃 I saw Tracker.withComputation in 2.10 and had a look on blaze, how hard can it be to make it work? 😅 I could quickly asynchronize some functions and I could write some self resolving helpers in a demo project, I was enthusiastic about it and wanted more 😬, when I saw no stringified [object Promise], but when I started to dive deeper, everyhing became async, like Blaze.renderWithData, maybe I did s.th. wrong and one false placed async has a huge consequence on the whole code base. At the moment, async pops up everywhere, what I don't want because then the whole API will be async, too, in future. I have problems now, that the Blaze.View is missing. I will keep on and just wanted to mention, that someone's working on it and want to know, if someone else gives it a try at the moment. Simply putting async everywhere doesn't seem the solution and I may think of another approach. Regards 💯 |
Probably, to make this happen, you will need to use |
Hi, I made some progress, talked to @jankapunkt and want to share a code snippet: view.js : 350
With this trick, htmljs will trigger an autorun as soon as its Promise resolves. So I could work inside Spacbars like Spacebars.dot and make them async, so that htmljs can handle the Promises. I ran the test suite and only 2 failed, but they also fail since 2.10, so my next steps are:
Problems are, that I couldn't manage to make this works so that Attributes work, but with my approach, it might be, that you can do the following:
{{asyncHelper.text}} or {{asyncCollectionHelper.method.text}} I'll keep you uptodate 😃 |
Hey @sebastianspiller, how is it going? Maybe you could share your changes so that we may check these tests as well. |
We had a meeting today with the blaze-async-workgroup and we came up with the first task / concept for blaze. <!-- This is a basic building block -->
{{#letAwait x=foo.q.w.e.r.t.y.bar y=baz}}
I can use {{x}} here and {{y}}, but `foo.q.w.e.r.t.y.bar` has to be a promise.
None of the prefix path (`foo`, `foo.q`, `foo.q.w`, etc.) cannot!
{{pending}}
Here either `x` or `y` is still pending.
{{rejected}}
Here either `x` or `y` is rejected.
{{/letAwait}}
<!-- End-user API (ideally) -->
<!-- We'd need to have a way of adding a `{{pending}}` and `{{rejected}}` blocks. -->
<template name="example">
<button className="js-click">Click me</button>
{{#if userClickedMeEvenNumberOfTimes}}
{{await foo.q.w.e.bar}}
{{/if}}
</template>
<!-- Desugared (ideally) -->
{{#if userClickedMeEvenNumberOfTimes}}
{{#letAwait temp1=foo}}
{{#letAwait temp2=temp1.q}}
{{#letAwait temp3=temp2.w}}
{{#letAwait temp4=temp3.e}}
{{#letAwait temp5=temp4.bar}}
{{temp5}}
{{/letAwait}}
{{/letAwait}}
{{/letAwait}}
{{/letAwait}}
{{/letAwait}}
{{/if}}
for the tasks, what we have is:
In these tasks, the latter three can be parallelized, but we need the letAwait building block |
I like the syntax for this. Is there a reason it is named One problem with svelte and its What is the plan to avoid this performance problem in blaze? |
I just wanted to make it stay in-align with
There's non... Yet. I've spent on it about an hour now, just making sure what is possible syntax-wise (including parser). Maybe a Suspense-like approach from React would work? That is, schedule updates "once in a while" and adjust DOM only if the update won't make it. But then again, it's a separate issue - Minimongo queries (or at least some of them) could rely on |
#409 should be linked here. |
I think with #412 we can close this one @jankapunkt ? |
Blaze currently auto-calls functions:
will lead to
bar
as output.However, changing
foo
to an async function like sowe will get for the same Template a
toString
output of a pending Promise:[object Promise]
However, we should be able to handle Promises in 2022 in any context. This would imply a huge PR but I think this is a crucial candidate for Blaze 3 and the future of Blaze
The text was updated successfully, but these errors were encountered: