{"id":13749006,"url":"https://github.com/GianlucaGuarini/icaro","last_synced_at":"2025-05-09T11:31:48.785Z","repository":{"id":66220175,"uuid":"95975666","full_name":"GianlucaGuarini/icaro","owner":"GianlucaGuarini","description":"Smart and efficient javascript object observer, ideal for batching DOM updates (~1kb)","archived":false,"fork":false,"pushed_at":"2018-08-07T20:43:04.000Z","size":90,"stargazers_count":572,"open_issues_count":3,"forks_count":29,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-05T14:09:03.010Z","etag":null,"topics":["object","object-listener","object-observer","observable","proxy"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GianlucaGuarini.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-07-01T16:31:30.000Z","updated_at":"2024-12-17T08:40:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"a37fb282-d9bc-4fdf-a7a5-1421a995bd88","html_url":"https://github.com/GianlucaGuarini/icaro","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GianlucaGuarini%2Ficaro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GianlucaGuarini%2Ficaro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GianlucaGuarini%2Ficaro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GianlucaGuarini%2Ficaro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GianlucaGuarini","download_url":"https://codeload.github.com/GianlucaGuarini/icaro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253240350,"owners_count":21876593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["object","object-listener","object-observer","observable","proxy"],"created_at":"2024-08-03T07:00:53.854Z","updated_at":"2025-05-09T11:31:46.006Z","avatar_url":"https://github.com/GianlucaGuarini.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# icaro\nA smart and efficient javascript object observer, ideal for batching DOM updates (__~1kb__)\n\n[![Build Status][travis-image]][travis-url]\n[![NPM version][npm-version-image]][npm-url]\n[![NPM downloads][npm-downloads-image]][npm-url]\n[![MIT License][license-image]][license-url]\n\n\u003cimg src='https://raw.githubusercontent.com/GianlucaGuarini/icaro/master/image.jpg' width='100%' /\u003e\n\n# Installation\n\nVia npm\n```shell\n$ npm i icaro -S\n```\n\n## Script import\n\nVia `\u003cscript\u003e`\n\n```html\n\u003cscript src='path/to/icaro.js'\u003e\u003c/script\u003e\n```\n\nVia ES2015 modules\n\n```js\nimport icaro from 'icaro'\n```\n\nVia commonjs\n\n```js\nconst icaro = require('icaro')\n```\n\n# Demos\n\n- [The Canvas](https://cdn.rawgit.com/GianlucaGuarini/icaro/v1.2.1/demos/canvas.html)\n- [The Counter](https://cdn.rawgit.com/GianlucaGuarini/icaro/v1.2.1/demos/counter.html)\n- [The Stress](https://cdn.rawgit.com/GianlucaGuarini/icaro/v1.2.1/demos/stress.html)\n\n# Performance\n\n`icaro` is really fast [compared to the other reactive libs](https://github.com/GianlucaGuarini/reactive-libs-bench) because it smartly throttles all the state changes.\n\n# Usage\n\n`icaro` will let you listen to all the changes happening in a javascript object or array, grouping them efficiently, and optimizing the performance of your listeners.\n\n```js\n\nconst obj = icaro({})\n\n// the variable \"changes\" here is a Map and the function is async\nobj.listen(function(changes) {\n  console.log(changes.get('foo')) // 'hi'\n  console.log(changes.get('bar')) // 'there'\n  console.log(changes.get('baz')) // 'dude'\n\n  // kill all the listeners\n  obj.unlisten()\n})\n\nobj.foo = 'hi'\nobj.bar = 'there'\nobj.baz = 'dude'\n\n```\n\n`icaro` will also let you listen to nested objects and all the non primitive properties added to an `icaro` object will be automatically converted into `icaro` observable objects.\n\n```js\nconst obj = icaro({})\n\n// listen only the changes happening on the root object\nobj.listen(function(changes) {\n})\n\nobj.nested = {\n\n}\n\nobj.nested.listen(function(changes) {\n  // listen only the changes of obj.nested\n})\n\nobj.nested.someVal = 'hello'\n\n```\n\n`icaro` is able also to listen changes in arrays. Any change to the items indexes will dispatch events.\n\n```js\n\n// Here a bit of hardcore async stuff\n\nconst arr = icaro([])\n\n// here you will get the index of the items added or who changed their position\narr.listen(function(changes) {\n  console.log(changes.get('0')) // 'foo'\n  console.log(changes.get('1')) // 'bar'\n  // kill all the listeners this included\n  arr.unlisten()\n\n  // add a brand new listener recursively.. why not?\n  arr.listen(function(changes) {\n    // the change was triggered by a 'reverse' and all indexes were updated\n    console.log(changes.get('0')) // 'bar'\n    console.log(changes.get('1')) // 'foo'\n  })\n\n  // update all the indexes\n  arr.reverse()\n})\n\n// initial dispatch\narr.push('foo')\narr.push('bar')\n\n```\n\nYou can also avoid unsubscribing (\"unlisten\") because `icaro` will automatically remove event listeners when the object is about to be garbage collected.\n\n# API\n\nAny `icaro` call will return a Proxy with the following api methods\n\n## icaro.listen(callback)\n\nListen any object or array calling the callback function asynchronously grouping all the contiguous changes via [setImmediate](https://developer.mozilla.org/en/docs/Web/API/Window/setImmediate)\n\n__@returns self__\n\n## icaro.unlisten(callback|null)\n\nUnsubscribing a callback previously subscribed to the object, if no callback is provided all the previous subscriptions will be cleared\n\n__@returns self__\n\n## icaro.toJSON()\n\nReturn all data contained in an `icaro` Proxy as JSON object\n\n__@returns Object__\n\n# Support\n\n`icaro` uses advanced es6 features like [Proxies](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy), [WeakMaps](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakMap), [Maps](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map) and [Symbols](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol) and __it targets only modern browsers__\n\nAll major evergreen browsers (Edge, Chrome, Safari, Firefox) [should be supported](http://caniuse.com/#search=Proxy)\n\n[travis-image]:https://img.shields.io/travis/GianlucaGuarini/icaro.svg?style=flat-square\n[travis-url]:https://travis-ci.org/GianlucaGuarini/icaro\n\n[license-image]:http://img.shields.io/badge/license-MIT-000000.svg?style=flat-square\n[license-url]:LICENSE.txt\n\n[npm-version-image]:http://img.shields.io/npm/v/icaro.svg?style=flat-square\n[npm-downloads-image]:http://img.shields.io/npm/dm/icaro.svg?style=flat-square\n[npm-url]:https://npmjs.org/package/icaro\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGianlucaGuarini%2Ficaro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGianlucaGuarini%2Ficaro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGianlucaGuarini%2Ficaro/lists"}