dy / xhtm

XHTM − eXtended Hyperscript Tagged Markup
MIT License
25 stars 2 forks source link

Async everything #26

Closed adamkiss closed 10 months ago

adamkiss commented 1 year ago

Hey Dmitry, thank you for the project!

I've been hacking it into a plugin for eleventy (https://11ty.dev) - https://github.com/adamkiss/eleventy-plugin-jstl/tree/async-components, and while everything mostly works, one thing I'm struggling with is async components, which in some cases might be asynchronous; making vhtml (or rather, the unescaped fork by Aral) into async function was easy, it has just one return, but I've been sort of stumped with xhtm.

My idea was that I'd basically defensively await everything, but I think I'm misunderstanding the main str.replace (and how to async that), and the internal counters/stacks are all out of sync, so I end up with a bunch of undefined.

I understand this is probably beyond the scope of what xhtm is, byt any tips/ideas you might have will help. thank you!

dy commented 1 year ago

Hm, it should not create troubles with async calls. Do you possibly have an example when async call messes up where normal call doesn't?

adamkiss commented 1 year ago

@dy as i said, it’s probably something I’m doing wrong - my naive fork is here - https://github.com/adamkiss/eleventy-plugin-jstl/blob/async-components/src/htm.mjs

what i’m doing in eleventy is loading all components from provided “includes directory”, then stringifying those and data into one hairy ball with the contents of the tagged literal and just… evaluating it. It’s incredibly dirty.

Edit: I've sort of put together an example here: https://github.com/adamkiss/eleventy-plugin-jstl/blob/main/experiments/async-html.mjs - ideally - and again, it's probably out of scope for xhtm - I'd call a single await html"whatever" and it'd magically resolve all promises and stuff, without actually awaiting the values inside ${}. At this point though, I'm okay with awaiting - still miles better than nunjucks and friends :D - and I would just like to get the <${Component}> call async

dy commented 1 year ago

await html`...` seems to work ok, no?

adamkiss commented 1 year ago

@dy In some (very simple cases).

const api = async _ => Promise.resolve('async')
const Paragraph = async ({children, ...props} = {}) => await html`<p>${children}</p>`
const multiple = await html`
    <${Paragraph}>${api()}<//>
    <${Paragraph}>${api()}<//>
`
const wrapped = await html`
    <${Paragraph}><${Paragraph}>${api()}<//><//>
`
console.log(multiple, wrapped)

outputs:

[
  Promise { '<p>[object Promise]</p>' },
  Promise { '<p>[object Promise]</p>' }
]

<p>[object Promise]</p>

Shame, but fair enough, awaiting the api() instead:

const multiple = await html`
    <${Paragraph}>${await api()}<//>
    <${Paragraph}>${await api()}<//>
`
const wrapped = await html`
    <${Paragraph}><${Paragraph}>${await api()}<//><//>
`
console.log(multiple, wrapped)

results in:

[ Promise { '<p>async</p>' }, Promise { '<p>async</p>' } ]

<p>[object Promise]</p>
dy commented 10 months ago

Ok, added in hyperf@1.7.0. You'd need to implement similar way.