All Projects → gullerya → Object Observer

gullerya / Object Observer

Licence: isc
Object Observer functionality of JavaScript objects/arrays via native Proxy

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Object Observer

Bach
Compose your async functions with elegance.
Stars: ✭ 117 (+32.95%)
Mutual labels:  async, observable, callback
Redux Most
Most.js based middleware for Redux. Handle async actions with monadic streams & reactive programming.
Stars: ✭ 137 (+55.68%)
Mutual labels:  async, observable
Metasync
Asynchronous Programming Library for JavaScript & Node.js
Stars: ✭ 164 (+86.36%)
Mutual labels:  async, callback
Continuable
C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)
Stars: ✭ 655 (+644.32%)
Mutual labels:  async, callback
Fibrous
Easily mix asynchronous and synchronous programming styles in node.js.
Stars: ✭ 183 (+107.95%)
Mutual labels:  async, callback
Vkbottle
Homogenic! Customizable asynchronous VK API framework
Stars: ✭ 191 (+117.05%)
Mutual labels:  async, callback
Taskmanager
A simple、 light(only two file)、fast 、powerful 、easy to use 、easy to extend 、 Android Library To Manager your AsyncTask/Thread/CallBack Jobqueue ! 一个超级简单,易用,轻量级,快速的异步任务管理器,类似于AsyncTask,但是比AsyncTask更好用,更易控制,从此不再写Thread ! ^_^
Stars: ✭ 25 (-71.59%)
Mutual labels:  async, callback
Sming
Sming - Open Source framework for high efficiency native ESP8266 development
Stars: ✭ 1,197 (+1260.23%)
Mutual labels:  async
Run Waterfall
Run an array of functions in series, each passing its results to the next function
Stars: ✭ 83 (-5.68%)
Mutual labels:  async
Keshi
A better in-memory cache for Node and the browser
Stars: ✭ 75 (-14.77%)
Mutual labels:  async
C Ares
A C library for asynchronous DNS requests
Stars: ✭ 1,193 (+1255.68%)
Mutual labels:  async
Javelin
[Mirror] RTMP streaming server written in Rust
Stars: ✭ 77 (-12.5%)
Mutual labels:  async
Network Idle Callback
Like requestIdleCallback, but for detecting network idle
Stars: ✭ 84 (-4.55%)
Mutual labels:  callback
Suave
Suave is a simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition.
Stars: ✭ 1,196 (+1259.09%)
Mutual labels:  async
Datakernel
Alternative Java platform, built from the ground up - with its own async I/O core and DI. Ultra high-performance, simple and minimalistic - redefines server-side programming, web-development and highload!
Stars: ✭ 87 (-1.14%)
Mutual labels:  async
Pfun
Functional, composable, asynchronous, type-safe Python.
Stars: ✭ 75 (-14.77%)
Mutual labels:  async
Magpie
🐦 Successor of my monkey Interpreter(support for class, linq, sql, net, http, fmt, json and A realtime syntax highlighting REPL).
Stars: ✭ 88 (+0%)
Mutual labels:  async
Async Retry
Retrying made simple, easy and async
Stars: ✭ 1,262 (+1334.09%)
Mutual labels:  async
Dns
Async DNS resolution for PHP based on Amp.
Stars: ✭ 82 (-6.82%)
Mutual labels:  async
Linq Async
C# LINQ Async extension methods library for async/await task.
Stars: ✭ 82 (-6.82%)
Mutual labels:  async

npm GitHub

Quality pipeline Codecov Codacy

Summary

object-observer provides a deep observation of a changes performed on an object/array graph.

Main aspects and features:

  • implemented via native Proxy (revokable)

  • observation is 'deep', yielding changes from a sub-graphs too

  • nested objects of the observable graph are observables too

  • changes delivered in a synchronous way by default, asynchronous delivery (experimental) is optionally available as per Observable configuration; more details here

  • observed path may optionally be filtered as per observer configuration; more details here

  • original objects are cloned while turned into Observables

  • array specifics:

    • generic object-like mutations supported
    • intrinsic Array mutation methods supported: pop, push, shift, unshift, reverse, sort, fill, splice, copyWithin
    • massive mutations delivered in a single callback, usually having an array of an atomic changes
  • typed array specifics:

    • generic object-like mutations supported
    • intrinsic TypedArray mutation methods supported: reverse, sort, fill, set, copyWithin
    • massive mutations delivered in a single callback, usually having an array of an atomic changes
  • intrinsic mutation methods of Map, WeakMap, Set, WeakSet (set, delete) etc are not observed (see this issue for more details)

  • following host objects (and their extensions) are skipped from cloning / turning into observables: Date, Blob, Error

Support matrix: CHROME61+ | FIREFOX60+ | EDGE16+ | NODE JS 8.10.0+

Performance report can be found here

Last versions (full changelog is here)

  • 4.2.1

    • documentation improved and updated
    • dependencies updated
    • Issue no. 73 - added DOM-like API of ObjectObserver
  • 4.1.3

  • 4.1.1

    • Issue no. 70 - automated version bump
    • unified Change object structure (so that it is always the same shape)
    • improved perf tests

For a preview/playground you are welcome to:

Install

Use regular npm install object-observer --save-prod to use the library from your local environment.

Additionally, a CDN deployment available (AWS driven), so one can import it directly:

import { Observable } from 'https://libs.gullerya.com/object-observer/x.y.z/object-observer.min.js';

Note: replace the x.y.z by the desired version, one of the listed in the changelog.

CDN features:

  • HTTPS only, no untrusted man-in-the-middle
  • highly available (with many geo spread edges)
  • agressive caching setup

Import object-observer as ES6 module:

import { Observable } from 'object-observer.min.js';

API

Library implements Observable API as it is defined here.

Additionally, from version 4.2.0 there is also 'DOM-like' API flavor, a one that resonating with DOM's MutationObserver, ResizeObserver etc from the syntax perspective. Under the hood it uses the same Observable mechanics. Read docs about this API flavor here.

This is experimental API until specified here otherwise.

Security

Security policy is described here. If/when any concern raised, please follow the process.

Examples

Objects
const
	order = { type: 'book', pid: 102, ammount: 5, remark: 'remove me' },
    observableOrder = Observable.from(order);

observableOrder.observe(changes => {
    changes.forEach(change => {
        console.log(change);
    });
});


observableOrder.ammount = 7;
//  { type: 'update', path: ['ammount'], value: 7, oldValue: 5, object: observableOrder }


observableOrder.address = {
    street: 'Str 75',
    apt: 29
};
//  { type: "insert", path: ['address'], value: { ... }, object: observableOrder }


observableOrder.address.apt = 30;
//  { type: "update", path: ['address','apt'], value: 30, oldValue: 29, object: observableOrder.address }


delete observableOrder.remark;
//  { type: "delete", path: ['remark'], oldValue: 'remove me', object: observableOrder }

Object.assign(observableOrder, { amount: 1, remark: 'less is more' }, { async: true });
//	- by default the changes below would be delivered in a separate callback
//	- due to async use, they are delivered as a batch in a single callback
//  { type: 'update', path: ['ammount'], value: 1, oldValue: 7, object: observableOrder }
//  { type: 'insert', path: ['remark'], value: 'less is more', object: observableOrder }
Arrays
let a = [ 1, 2, 3, 4, 5 ],
    observableA = Observable.from(a);

observableA.observe(changes => {
    changes.forEach(change => {
        console.log(change);
    });
});


//  observableA = [ 1, 2, 3, 4, 5 ]
observableA.pop();
//  { type: 'delete', path: [4], value: undefined, oldValue: 5, object: observableA }


//  now observableA = [ 1, 2, 3, 4 ]
//  following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.push('a', 'b');
//  { type: 'insert', path: [4], value: 'a', oldValue: undefined, object: observableA }
//  { type: 'insert', path: [5], value: 'b', oldValue: undefined, object: observableA }


//  now observableA = [1, 2, 3, 4, 'a', 'b']
observableA.shift();
//  { type: 'delete', path: [0] value: undefined, oldValue: 1, object: observableA }


//  now observableA = [ 2, 3, 4, 'a', 'b' ]
//  following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.unshift('x', 'y');
//  { type: 'insert', path: [0], value: 'x', oldValue: undefined, object: observableA }
//  { type: 'insert', path: [1], value: 'y', oldValue: undefined, object: observableA }


//  now observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.reverse();
//  { type: 'reverse', path: [], object: observableA } (see below and exampe of this event for nested array)


//  now observableA = [ 'b', 'a', 4, 3, 2 ]
observableA.sort();
//  { type: 'shuffle', path: [], object: observableA } (see below and exampe of this event for nested array)


//  observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.fill(0, 0, 1);
//  { type: 'update', path: [0], value: 0, oldValue: 2, object: observableA }


//  observableA = [ 0, 3, 4, 'a', 'b' ]
//  the following operation will cause a single callback to the observer with an array of 2 changes in it)
observableA.splice(0, 1, 'x', 'y');
//  { type: 'update', path: [0], value: 'x', oldValue: 0, object: observableA }
//  { type: 'insert', path: [1], value: 'y', oldValue: undefined, object: observableA }


let customer = { orders: [ ... ] },
    oCustomer = Observable.from(customer);

//  sorting the orders array, pay attention to the path in the event
oCustomer.orders.sort();
//  { type: 'shuffle', path: ['orders'], object: oCustomer.orders }


oCustomer.orders.reverse();
//  { type: 'reverse', path: ['orders'], object: oCustomer.orders }

Arrays notes: Some of array operations are effectively moving/reindexing the whole array (shift, unshift, splice, reverse, sort). In cases of massive changes touching presumably the whole array I took a pessimistic approach with a special non-detailed events: 'reverse' for reverse, 'shuffle' for sort. The rest of these methods I'm handling in an optimistic way delivering the changes that are directly related to the method invocation, while leaving out the implicit outcomes like reindexing of the rest of the Array.

Observation options

object-observer allows to filter the events delivered to each callback/listener by an optional configuration object passed to the observe API.

In the examples below assume that callback = changes => {...}.

let user = {
        firstName: 'Aya',
        lastName: 'Guller',
        address: {
            city: 'of mountaineers',
            street: 'of the top ridges',
            block: 123,
            extra: {
                data: {}
            }
        }
    },
    oUser = Observable.from(user);

//  path
//
//  going to observe ONLY the changes of 'firstName'
oUser.observe(callback, {path: 'firstName'});

//  going to observe ONLY the changes of 'address.city'
oUser.observe(callback, {path: 'address.city'});

//  pathsOf
//
//  going to observe the changes of 'address' own properties ('city', 'block') but not else
oUser.observe(callback, {pathsOf: 'address'});
//  here we'll be notified on changes of
//    address.city
//    address.extra

//  pathsFrom
//
//  going to observe the changes from 'address' and deeper
oUser.observe(callback, {pathsFrom: 'address'});
//  here we'll be notified on changes of
//    address
//    address.city
//    address.extra
//    address.extra.data
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].