These are chat archives for ractivejs/ractive

8th
Jan 2018
Anatoli Radulov
@avoto
Jan 08 2018 00:57
I am also in favor of the mustache syntax.
Paul Maly
@PaulMaly_twitter
Jan 08 2018 01:02
I think Svelte's syntax of {{#await /}} block is very laconic and clear. Perhaps, we can just steal this idea from @Rich-Harris as usual )))
Chris Reeves
@evs-chris
Jan 08 2018 02:40
looking at the svelte impl, it looks like the one sorta weird thing for me is that undefined, as opposed to a promise, is considered to be resolved promise with the value undefined
so with {{#await foo}}...{{then thing}}done: {{thing}}{{/await}} results in done: undefined when foo is undefined
with ractive, you get done: because undefined is not rendered unless you force it by turning it into a string directly
Joseph
@fskreuz
Jan 08 2018 05:06
An empty render sounds about right. undefined supposed to represent nothingness. undefined rendering something is a footgun, and it won't be long before you start writing undefined-guards all over the place if we went this route. :D
I'd say just do the empty render like Ractive normally does and let the author decide what to do with that. One can always {{#if thing === undefined }}undefined{{/if}} if they really want to render "undefined". Also avoids cases where you'd suddenly have "Remaining balance: undefined" on your pages.
Chris Reeves
@evs-chris
Jan 08 2018 05:18
so you wouldn't just skip the whole block if the val === undefined?
Paul Maly
@PaulMaly_twitter
Jan 08 2018 08:50
If foo === undefined we can skip whole block, but if foo is promise but resolved with undefined result we need to render "then" block with this result.
Paul Maly
@PaulMaly_twitter
Jan 08 2018 11:10
Also I think the main idea is - works as Ractive always does. So, seems we need to be able also do that: {{#await foo}} defined {{else}} undefined {{/await}}
And it'll be absolutelly awesome!
Joseph
@fskreuz
Jan 08 2018 12:38
If the expression in {{#await expression}} isn't a promise, Svelte skips ahead to the then section.
https://svelte.technology/guide#await-blocks
So I guess that's a yes, you wouldn't skip the then if the expression is undefined, or more generally, not a promise. It becomes the resolved value.
Joseph
@fskreuz
Jan 08 2018 12:44
Also in line with how Promise.all works - supply it a non-promise, then the value becomes the resolved value at that index. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
... and how then calls the first callback if the previous then returned nothing, i.e. promise.then(v => /* do nothing, return nothing */).then(d => /* d is undefined and not v, I still get called */)
Paul Maly
@PaulMaly_twitter
Jan 08 2018 15:42
Undefined actually is not a value, so I think we need to skip then block. And use {{else}} to detect this case.
But if value is not a promise, so it's a good idea to render {{then val }} block instantly. Like Promise.resolve(val)
Joseph
@fskreuz
Jan 08 2018 15:51

Undefined actually is not a value, so I think we need to skip then block. And use {{else}} to detect this case.

But that would go against the entire concept of promises, thens, and catch. Also, this.

Chris Reeves
@evs-chris
Jan 08 2018 15:53
FWIW, the svelte repl await example has a guard {{#if promise}}{{#await promise}}...{{/await}}{{/if}}
Paul Maly
@PaulMaly_twitter
Jan 08 2018 15:53
Actually, this is a little bit incorrect
Chris Reeves
@evs-chris
Jan 08 2018 15:54
I get why, but it seems a little strange to me that you'd want to run the block if the data clearly isn't there yet
it fits with sveltes more minimalistic approach, but ractive is already far from minimal
Paul Maly
@PaulMaly_twitter
Jan 08 2018 15:54
I think {{#await promise}} != Promise.all([promise])
Joseph
@fskreuz
Jan 08 2018 15:56
That was just an example, that JS accepts a promise and a non-promise of whatever value, and that the then will run either way, resolving with the non-promise or the resolved value of the promise.
Hmm... now that I think about it.
If the path was initially undefined, and you stuck a promise onto it.
Paul Maly
@PaulMaly_twitter
Jan 08 2018 15:58
{{#await promise}} Pending... {{then res}} Resolved with {{res}} {{catch err}} Rejected with {{err}} {{ else }} Promise undefined {{/await}}
I think it's could be full construction
Chris Reeves
@evs-chris
Jan 08 2018 15:59
oh my
Joseph
@fskreuz
Jan 08 2018 15:59
The enclosing if-guard starts to make sense tho...
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:00
Any block is not required
Joseph
@fskreuz
Jan 08 2018 16:19
I think this is reasonable enough. This way, await can follow JS promise semantics (resolve value or wait for promise resolved value). Guarding against undefined is the user's responsibility.
{{#if value}}
  {{#await value}}
    Pending
  {{ then v }}
    Resolved {{v}}
  {{ catch e }}
    Error {{e}}
  {{/await}}
{{else}}
  undefined or some falsy
{{/if}}
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:20
But why {{#each }} block has another approach?
{{#each arr}} {{else}} {{/each}}
I never use each like thiz
{{#if arr}} {{#each arr}}...{{/each}}} {{else}} ...{{/if}}
Joseph
@fskreuz
Jan 08 2018 16:25
You would have before it was implemented, when you only had regular sections to work with (pre-handlebars Ractive).
I remember doing that around 0.4
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:29
Yep, but now we have the more laconic syntax, so I never use #if like this.
I think await block should be very similar to existing blocks, like each
Chris Reeves
@evs-chris
Jan 08 2018 16:32
looking at the current impl, I agree that {{else}} should be allowed
however, I think it should only apply to undefined and not any other falsey values
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:34
Yep
value should be resolved even if it's not a promise like Promise.resolve(value)
Chris Reeves
@evs-chris
Jan 08 2018 16:34
the current PR just dies when trying to parse {{#await}}{{else}}{{/await}} because it is normally allowed for blocks, but not in a compatible way
Joseph
@fskreuz
Jan 08 2018 16:43
Couldn't really wrap my head around the idea why there's a special case for undefined when Promise.resolve(undefined) and Promise.resolve(somethingNotUndefined) would trigger the same callback.
That's unless the only values ever valid for {{#await}} is a promise or undefined (and throws an error if neither one)
Chris Reeves
@evs-chris
Jan 08 2018 16:45
99% for consistency with {{#with}} and {{#each}}
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:45
Seems undefined is always is special case
Chris Reeves
@evs-chris
Jan 08 2018 16:46
they allow {{else}} for falsey values
and if for some reason you actually want undefined to get to your then block, Promise.resolve(undefined) would do it
Paul Maly
@PaulMaly_twitter
Jan 08 2018 16:47
Because it's mean "no value"
Chris Reeves
@evs-chris
Jan 08 2018 16:48
the main difference is that null, false, {}, 0, and '' still make it through to the then because they are some sort of value
oh, and []
ractive has a somewhat overzealous definition of falsey
it usually works well in practice, though
Paul Maly
@PaulMaly_twitter
Jan 08 2018 17:47
Maybe to simplify block construction we could think about these variants:
{{#await promise: res, err}} {{#if res}} Resolved with {{res}} {{/if}} {{#if err}} Rejected with {{err}} {{/if}} {{ else }} Undefined promise {{/await}}
OR
Chris Reeves
@evs-chris
Jan 08 2018 17:51
the problem with that is res could be a legitimate falsey value
Paul Maly
@PaulMaly_twitter
Jan 08 2018 17:52
{{#await promise }} {{#if @result}} Resolved with {{@result}} {{/if}} {{#if @error}} Rejected with {{@error}} {{/if}} {{ else }} Undefined promise {{/await}}
Joseph
@fskreuz
Jan 08 2018 18:24

ractive has a somewhat overzealous definition of falsey

Ractive's definition of falsey closely ressembles PHP's, where empty arrays are also falsey - which I find convenient. No length checks everywhere or wrap-in-map operations.

Paul Maly
@PaulMaly_twitter
Jan 08 2018 19:28
Agree