Hacker News new | past | comments | ask | show | jobs | submit login

This has nothing to do with it. I love promises but they are truly limiting.

Here is an example of how promises limit the power of mobx

https://twitter.com/spion/status/958906847385341952

Another example relevant in node is continuation-local-storage (equivalent to threadlocal storage). Implementing it on top of generators or other "chainable / thenable" abstractions is trivially easy. Implementing it on top of native promises and async/await is impossible without deep hooks into the platform.

More examples here: https://spion.github.io/posts/es7-async-await-step-in-the-wr... (see the second part)

We should've paused on async-await and waited for jhusain's compositional functions: https://github.com/jhusain/compositional-functions

In the meantime generator based libraries would've properly explored the whole breadth of power that co-routines can give you, creating cowpaths to be paved by TC39.

Promises make trade-offs, and they end up with a design that is generally good and can be used well in some number of situations. But not all. Not nearly enough to get first class syntax support that makes them privileged over all other solutions.




Gorgi Kosev's post highlights a very nice use case for generators (database transactions). However, in all my JavaScript over the last few years, that is the only good use case I've found so far in my code base for generators. In all other use cases I've come across, async-await works just fine, and has a much nicer syntax to work with.


I elaborated that case in the most detail, but there are many other problems that generators solve mentioned in the blog post. Another very common one is getting the current user that initiated the request (or maybe their session), which you need to pass around to all your functions/classes.

What if you could simply `yield getCurrentUserSession` and the engine which ran the toplevel generator returned it back to you?

jhusein's compositional functions solved the syntax issue.


MobX is horribly opinionated, a monstruous abstraction of spaghetti, and you're saying Promises limit it?


MobX is the most powerful front end development library on the market right now. It single-handedly solves the cache invalidation problem in a performant way, and its pluggable into any framework.

And yes, promises limit it.


How does one measure power? What market?


By actually using the thing being criticised instead of giving it the middlebrow dismissal.

The "market" of application state management libraries.


Frankly, S.js looks better. Simple and performant.


Slightly confusing api, no structural comparison, no adapters for popular frameworks (e.g. S.js-react or S.js-preact), no laziness (computations are recomputed even if they're not requested by reactions).


Why use react when you can use Surplus which is based on S.js? Surplus is the fastest among all of the JS frameworks and supports JSX.

"Slightly confusing" == I'm not familiar with it. Not really an objection.

"No structural comparison": don't know what this is supposed to mean.

Re: laziness, actually redundant recomputations are not performed. Not sure where you go that impression.


I don't want to use surplus because e.g. I want to use well developed UI components or toolkits like blueprintjs, which is implemented on top of React.

Slightly confusing is a real objection. MobX strives to implement transparent reactive programming, where the way you access, update and transform values works exactly like it would with regular objects. S.js has a worse learning curve.

Redundant computations are computed; see: https://codepen.io/anon/pen/vdWomE?editors=0010

even though the completed() computed isn't used anywhere, the reduction is still being recomputed every time todo state changes


> MobX strives to implement transparent reactive programming, where the way you access, update and transform values works exactly like it would with regular objects. S.js has a worse learning curve.

Hardly: reactive values are get/set functions, and you create new ones with S(() => ...). That's it.

MobX's attempt at transparency yields inescapable and surprising corner cases.

> Redundant computations are computed; [...] even though the completed() computed isn't used anywhere, the reduction is still being recomputed every time todo state changes

Incorrect. The todos binding is an SArray not a regular array [1]. See my modified version where I log the events to the console [2].

[1] https://github.com/adamhaile/S-array

[2] https://codepen.io/anon/pen/KQyOyZ


The number of tricky corner cases in MobX are very few. Also, once the implementation switches to proxies the vast majority will disappear.

I'm willing to accept a few corner cases as long as there is a large common subset of functionality that works both with and without a small number of decorators. This can be utilised to write models that can be used in both a reactive and a non-reactive context with a different set of decorators injected in. S.js looks too invasive to do this.

Your codepen has no completed todo count. Why are the recomputations logged every time here?

https://codepen.io/anon/pen/vdWomE?editors=0010

> That's it.

What about the poorly named "S.freeze"


> Your codepen has no completed todo count. Why are the recomputations logged every time here?

Because you can't apply reduce any other way. It's a computation defined over a whole collection. To incrementalize it, you'd need to be able to invert whatever function you're trying to apply in order to arbitrarily undo and redo the operation as elements are added/removed. This is literally impossible in general as not all functions have inverses.

You should also use the SArray methods directly rather than embedding within S(): https://codepen.io/anon/pen/NyXqjB

Edit: you can see a semi-incremental version exploiting map's semantics here: https://codepen.io/anon/pen/KQZddK

If you look at the docs for SArray, you see they describe that map avoids recomputation.

> What about the poorly named "S.freeze"

What would you call it? S.atomic? I don't see how the existing name is particularly unsuitable.


> Because you can't apply reduce any other way.

In mobx, an unused computed will not run or recompute until its requested by a side effect (an autorun reaction, an observer component etc).

Example:

https://jsfiddle.net/ycufg9d3/

We use this to great extent in our application, by only rendering components that are visible in the viewport at the moment.

You can also keep its cached value alive, but not recompute it until needed by implementing a reaction that observes a computed but doesn't request its value. This will keep the entire computation graph cached but idle and partially dirty until the value is requested, at which point only stale dependencies will be recomputed. This can be extremely powerful: for example you can implement a state tree undo/redo by implementing serialize, then observing the serialize computed for the root item without requesting its value (keeping things cached) and only requesting recomputations when certain sufficient number of mutations are made. (with the vast number of reused values being structurally shared between undo/redo states)

> What would you call it? S.atomic? I don't see how the existing name is particularly unsuitable.

Yes atomic would be an improvement. Freeze only makes sense if you are thinking in terms of FRP signals in time, and its unclear whether the abstraction tries to hide its signal underpinnings or expose them (its somewhere inbetween)


No structural comparison:

MobX will stop dependant recomputation if the new value of an intermediate recomputation is equal to the previous value.

You also have the option of using structural equality instead of reference equality (and also you can use any custom equality comparison function)

https://mobx.js.org/refguide/computed-decorator.html#options...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: