@patrick-steele-idem and I have discussed adding a tag to marko's core that handles streaming in an elegant way.
The syntax that we're looking at is the <on> tag:
<ul>
<on(user in data.usersStream)>
<li>${user.name}</li>
</on>
</ul>
We'd also support a more verbose syntax for generic EventEmitters:
<on('data' as user in usersStream until 'end')>
Note: <for(x in stream)> was considered, but it would complicate the looping logic of regular for loops and require the stream logic to be present even for templates that never make use of it. We need something that is syntactically different so we can distinguish at compile time.
Note 2: we also considered <for-async(x in stream)> and <for await(x in stream)> however <on> has the benefit of making sense when used with any EventEmitter.
In many ways, the <on> tag will be similar to the <await> tag (previously <async-fragment>), however the <on> tag will also flush multiple times throughout it's rendering cycle.
There is a tradeoff to consider around flushing. If we flush after each iteration, content will be pushed to the browser sooner, but if we buffer a few iterations and gzip is enabled, the resulting payload will be smaller. We need a good default for flushing and an easy, intuitive way to configure it.
We also need to figure out what should be provided by the tag, and what interesting use cases we want to support. One that comes to mind immediately is infinite scrolling.
All that said, here is my proposed set of attributes for the <on> tag:
@var - parsed from the argument, the variable to be used inside the body of the tag
@event - parsed from the argument, the name of the event to listen to, defaults to "data"
@endEvent - parsed from the argument, the name of the event that signifies the end of the loop, defaults to "end"
@data-provider - parsed from the argument, the stream or emitter we're listening to
@name - the name of the <on> tag. used for debugging and the show-after attribute
- FUTURE:
@client-reorder - the <on> tag will not block the rest of the page, JS is required on client
- FUTURE:
@show-after - when client-reorder is set to true then displaying this instance's content will be delayed until the referenced <await> or <on> instance is shown.
@buffer-count - how many iterations of the <on> tag to buffer before flushing
@buffer-duration - if the time since the last flush is greater than the buffer duration, then the <on> tag will flush its buffer, regardless of the current buffer count
@timeout - if the time since the last chunk of data was emitted is greater than the timeout, then the <on> tag will timeout
@total-timeout - if the time since the rendering started is greater than the total timeout, then the <on> tag will timeout
@error-message - a message that is shown if the stream emits an error
@timeout-message - a message that is shown if the stream times out
- FUTURE:
@placeholder-message - a message that is shown while the <on> tag is streaming
@empty-message - a message that is shown if the stream ends without emitting data
@finish-message - a message that is shown when/if the stream completes successfully
Also, we'll provide <on-placeholder>, <on-error>, <on-timeout>, <on-empty>, and <on-finish> as alternatives *-message attributes.
@patrick-steele-idem and I have discussed adding a tag to marko's core that handles streaming in an elegant way.
The syntax that we're looking at is the
<on>tag:We'd also support a more verbose syntax for generic EventEmitters:
In many ways, the
<on>tag will be similar to the<await>tag (previously<async-fragment>), however the<on>tag will also flush multiple times throughout it's rendering cycle.There is a tradeoff to consider around flushing. If we flush after each iteration, content will be pushed to the browser sooner, but if we buffer a few iterations and gzip is enabled, the resulting payload will be smaller. We need a good default for flushing and an easy, intuitive way to configure it.
We also need to figure out what should be provided by the tag, and what interesting use cases we want to support. One that comes to mind immediately is infinite scrolling.
All that said, here is my proposed set of attributes for the
<on>tag:@var- parsed from the argument, the variable to be used inside the body of the tag@event- parsed from the argument, the name of the event to listen to, defaults to "data"@endEvent- parsed from the argument, the name of the event that signifies the end of the loop, defaults to "end"@data-provider- parsed from the argument, the stream or emitter we're listening to@name- the name of the<on>tag. used for debugging and theshow-afterattribute@client-reorder- the<on>tag will not block the rest of the page, JS is required on client@show-after- whenclient-reorderis set to true then displaying this instance's content will be delayed until the referenced<await>or<on>instance is shown.@buffer-count- how many iterations of the<on>tag to buffer before flushing@buffer-duration- if the time since the last flush is greater than the buffer duration, then the<on>tag will flush its buffer, regardless of the current buffer count@timeout- if the time since the last chunk of data was emitted is greater than the timeout, then the<on>tag will timeout@total-timeout- if the time since the rendering started is greater than the total timeout, then the<on>tag will timeout@error-message- a message that is shown if the stream emits an error@timeout-message- a message that is shown if the stream times out@placeholder-message- a message that is shown while the<on>tag is streaming@empty-message- a message that is shown if the stream ends without emitting data@finish-message- a message that is shown when/if the stream completes successfullyAlso, we'll provide
<on-placeholder>,<on-error>,<on-timeout>,<on-empty>, and<on-finish>as alternatives*-messageattributes.