
Icaro – Smart Javascript object observer, ideal for batching DOM updates - gianlucaguarini
https://github.com/GianlucaGuarini/icaro
======
franciscop
Nice, I made something really similar but found it had a bunch of issues. Some
of which I don't see addressed here.

When setting an object or array, it will always trigger since the equal
comparison will return false even if they have the same { key: value } pairs:

    
    
        target[property] !== value
    

Speaking of which, sub-properties are not being listened to from the root
(only if manually listened to on the sub-object):

    
    
        obj.foo = { bar: 'baz' }; // triggers
        obj.foo.bar = 'whatever'; // never triggers the base listener
    

The only realistic automatic way to listen to them is to add a trap for the
_get_ , which will proxify the return value if it's an object or array. This
has it's own set of errors and turns into a nasty set of edge cases, which is
the main reason I never got to release what I was doing. I see in Icaro you
Proxify it manually and adding some props on the setter, which leads to this
not working as expected:

    
    
        const obj = icaro({ foo: { bar: 'baz' } });
        obj.foo.bar = 'baz2';  // Nothing triggers

------
akx
The array example is a little weird.

    
    
        // no events here
        arr.map(v => v + '-meh')
    

Since `.map` doesn't mutate the array in the first place, surely no one would
expect observation events to occur anyway?

~~~
logiccraft
Indeed. This functionality really worries me.

Why would a non-mutation trigger listeners?

~~~
gianlucaguarini
you are absolutely right, map doesn't belong to the mutational methods. Fixed
in v1.1.1 thank you for your feedback

------
iamleppert
Isn't this just queuing up the actual, real work on the event loop?

Of course its faster to call setImmediate a bunch of times to defer work, than
it is to actually DO the work. It is useless to compare a synthetic benchmark
for what is fundamentally a task that involves drawing something to the
screen, without measuring the time it takes to finish all those tasks. The
actual performance will, of course, be determined by how many DOM mutations
are occurring, and the relative layout complexity of each. There will be a
benefit for lots of really small, expensive mutations that _could_ be batched
together, but who designs their applications like that? Oh, wait...

At least, that's my understanding of looking at the source for a few minutes.
Maybe I'm missing something, but I don't see any real algorithm at work here,
just work that is shifted around to make a benchmark look good.

A better benchmark would be to use this in a real world, non-trivial use-case
somehow and measure the framerate. But I can save you the effort: It's not
going to win out over a well designed application that does direct DOM
manipulation. Period.

~~~
roucoulawan
But is Icaro more on listening changes on javascript objects, in a general
manner, better than just the DOM ones?

I think that this light lib could be actually a cool toy to use if you need
for example to do some simple app state listened manipulations on the node
backend side.

Otherwise, that is true, I would maybe still prefer to use frontend side some
well-designed frameworks like redux-Rx or redux-react

------
TheAceOfHearts
Last time I tried Proxies, their performance wasn't very good. It would be
great to see a few benchmarks.

What advantages would this give you over using persistent data structures [0]
with memoized selectors? When using immutable data structures, you can shift
the responsibility of providing updates up to the caller. In my experience,
that usually means code that's easier to debug and test.

[0]
[https://en.wikipedia.org/wiki/Persistent_data_structure](https://en.wikipedia.org/wiki/Persistent_data_structure)

~~~
gianlucaguarini
Here you can see some bench results comparing the most popular reactive
javascript libs [https://github.com/GianlucaGuarini/reactive-libs-
bench](https://github.com/GianlucaGuarini/reactive-libs-bench) icaro included

~~~
slaymaker1907
Why is icaro so much more performance? It's two orders of magnitude faster
than the other frameworks if I'm reading the results correctly.

~~~
gianlucaguarini
please check the readme file
[https://github.com/GianlucaGuarini/icaro#performance](https://github.com/GianlucaGuarini/icaro#performance)
there it's explained

------
carussell
If this is meant to target modern browsers, what's the use of this check and
fallback for IE's obsolete API?

    
    
        if (global.addEventListener) {
          global.addEventListener('message', onGlobalMessage, false);
        } else {
          global.attachEvent('onmessage', onGlobalMessage);
        }

~~~
gianlucaguarini
Well that's a fork of
[https://github.com/YuzuJS/setImmediate](https://github.com/YuzuJS/setImmediate)
so it must be removed! Would you mind making a pull request?

~~~
carussell
> Would you mind making a pull request?

I do mind, so no thanks. I've written at length about why[1][2].

I'm not using the project, but you can consider the feedback in my last
comment as a bug report if you like.

1\. [http://www.colbyrussell.com/2015/05/31/git-and-its-
hubs.html](http://www.colbyrussell.com/2015/05/31/git-and-its-hubs.html)

2\. [https://github.com/colbyrussell/keeping-a-low-profile-on-
git...](https://github.com/colbyrussell/keeping-a-low-profile-on-github)

~~~
orf
I sort of understand why you want to avoid GitHub, thank you for sharing those
links. All in all though to make a small pull request like the one in
question, it takes about 2 minutes and three clicks to do so.

Not that you should do so if you don't want to, but this is a _good_ thing for
OS projects. The barrier to entry and contribute is non-existent - if you want
to fix something small just press 'edit', make your changes in the browser and
press 'submit merge request'.

No cloning, no local installs, no fuss. You can do it from your phone, on a
bus.

------
albertTJames
I think I have a smaller one [https://github.com/albertbuchard/promets-
moi](https://github.com/albertbuchard/promets-moi)

~~~
foota
The parent one seems to handle more, nested properties and batching?

~~~
albertTJames
hmm not sure what batching means in this context but nested property works.

~~~
gianlucaguarini
ehy thanks for linking to your project it looks great! Regarding the batching
strategy icaro smartly groups the object changes via setImmediate helping in
case you need to change many properties on the same object for example:

obj.name = 'foo' obj.surname = 'bar'

in this case icaro will dispatch only one event optimizing the listeners to
avoid unnecessary redundant events

