13 ms·
Not clear why HTML rendering needed to be infected with async. None of the example code has a clear need for async - even the `is_admin()` method would be a pre
by rafram 2y ago
Not clear why HTML rendering needed to be infected with async. None of the example code has a clear need for async - even the `is_admin()` method would be a prefetched property in any reasonable database model.
- hansvm 2y agoYour counterpoint still naturally involves something like async _somewhere_ (your proposal is just to move it out of the HTML rendering and into an initial data-gathering stage). If you accept that premise then the question is just where the async code goes. While on some level it makes sense for HTML rendering to be a pure function where the inputs are gathered from elsewhere (potentially asynchronously), it looks like htmy wants to make it easy to define hierarchies of components. Instead of `is_admin()`, imagine a dashboard whose layout is stored in a database, supporting configurable charts of various flavors. The heterogeneity of the data supporting different types of charts makes it hard to efficiently pull data in a single SQL query (equivalently, any reasonable database model), so somewhere in your code you're pulling a bunch of data asynchronously, and somewhere else you're rendering it. The question, still, is "where?" Going back to the idea of htmy defining hierarchies of components, imagine how annoying it would be to have to manually grab all the data for a "reporting page" component only to feed it straight back into the renderer -- either having to duplicate the hierarchial structure when feeding data into the renderer (a technique some UI libraries employ, though I don't like it) -- or having to come up with a method for flattening that hierarchy when instantiating the component (another technique some UI libraries employ, one I like more for small projects and less for large ones). They solve that (to the extent that you think it needs solving) by bundling all that background logic into the components themselves. Did they really need to implement that recursively instead of just walking the hierarchy, gathering the data up-front, and populating it? Eh. The code winds up being similar either way, and either way it definitely forces async back into the middle of HTML rendering. Mind you, that tends to either make some applications hard to build or to cause the framework to explode in complexity over time as people need new and new ways to say "yes, re-render this thing; no, re-render that other thing, but don't grab its data, ...." There's enough less particularly annoying code involved though that fat, smart components are a natural place for people to gravitate. Unrelated to htmy completely, a technique I like from time to time even for problems which don't need async per se (and I'm usually using lower-level languages, so the implementation is some sort of more manual continuation pattern, but all those things are basically async, so I won't dwell on the details) is explicitly designing pausable/restartable structures for long-running computations. It's about as easy to write as purely iterative code, and you can run the result as purely iterative with no runtime overhead, so the downsides are low. It opens the door though to easily tuning how long you defer invariant maintenance (too infrequent and your algorithm devolves to the slow thing it's replacing, too frequent and the overhead isn't worth it), easily checkpointing a computation, adding other custom runners for an algorithm (like animating its progress), .... I can absolutely see a use-case for wanting to visualize each step of an HTML rendering, or log OS network counters after each step, and so on. Python's async isn't really the right tool for the job for that (it's hard to modify the runtime to support them without building quite a lot of nonsense from scratch), but async in the abstract isn't bad at all per se.
- deleted 2y ago[deleted]
- mattigames 2y agoImagine you have 2 big components, one fetches from an third-party API and the other from your backend, this way they can load at the same time instead of sequentially.
- ramon156 2y agoBecause checking for two conditions is impossible? This seems like a solution for a non-existent problem. I could be missing something
- anentropic 2y agoI was imagining more like you have a Django view that does all the async data fetching and then you hand off the results to a 'dumb' page component that does only rendering I guess the point is to have components know how to fetch their own data, particularly when combining with HTMX and having backend return page fragments that correspond to components. But maybe this makes more sense in React than it does when translating the pattern back to server-side? e.g. same author has this https://github.com/volfpeter/fasthx?tab=readme-ov-file#htmy-templating https://github.com/volfpeter/fasthx?tab=readme-ov-file#htmy-... which is doing that, but there's still a 'view' endpoint. Why not put the data fetch code there and have 'dumb' components that don't need to be async?
- mattigames 2y agoIt seems like the view endpoint would be for functionality shared the full view, like auth safeguards and such, while the components would fetch the data they need; this would make it so you don't need to pass around the data to the view and save a few lines of code; of course this is not compatible with the idea of having "dumb" components vs "logic" ones like people do in React and alike.
- volfpeter 2y agoComponents don't really need to fetch anything, they don't need to be smart. It's up to you where data fetching happens. If you look at fasthx for example, you'll see that routes/views normally handle your business logic and fasthx does the rendering (now with Jinja or htmy). With Jinja for example, it can only work like this. With htmy, you have more flexibility (which can be an advantage but of course it can also be misused). Async components can be handy for example when you need to load files. See the Snippet utility and the markdown support in the lib. https://volfpeter.github.io/htmy/examples/markdown/ https://volfpeter.github.io/htmy/examples/markdown/
- scotty79 2y agoAsync infrastructure allows your stuff to be sync or async. While sync infrastructure forces your stuff to be sync. If anything sync (not async) infects everything you do. Of course it depends if you call the infrastructure (then it's better for it to be sync) of if the infrastructure calls you (then it's better to be async). Rendering engine is something you rarely call, but it often calls your functions.
- rafram 2y agoYes, and that’s the worst part of async. That’s why you need to be very strategic about where you introduce it into your code in order to minimize the number of functions it infects, not give up and write a framework that’s all async for no good reason. https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- scotty79 2y agoYes. But you should be equally strategic about introducing sync code into your platform. Because making your platform sync basically makes it only be able to call sync functions of your code. It's not that async infects. It's sync that infects and restricts. We are just used to it by default. The fact that we started from sync was the cause of all the trouble of rpc because everything outside of CPU is innately async. So make your utility functions sync whenever you can but make your platforms and frameworks async.
- rafram 2y agoI just completely disagree. Async is syntactic sugar that can be reduced to sync code with callbacks. It doesn’t exist on equal footing. If you want to call sync code from async code, you just… call it. If it performs blocking IO, it’ll block, but that’s exactly what it would do if called from other sync code, too. By contrast, calling async code from sync code requires a special blocking wrapper (Python) or unavoidably breaks control flow (JavaScript).