Security News
NVD Backlog Tops 20,000 CVEs Awaiting Analysis as NIST Prepares System Updates
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
object-observer
Advanced tools
Object observer utility provides simple means to (deeply) observe specified object/array changes; implemented via Proxy; changes delivered in a synchronous way
Observation of a changes performed on an object (array being a subtype of it) is a MUST HAVE facility in JavaScript world.
Native facility would be the best solution for this, since it may provide non-intrusive observation wihtout 'touching' the original objects, but seems like ES is not yet mature enough for that.
Present library attempts to provide this functionality in a most clean and performant way. Main aspects:
pop
, push
, shift
, unshift
, reverse
, sort
, fill
, splice
(see below for more info on changes delivery for these)Map
, WeakMap
, Set
, WeakSet
like set
, get
, delete
etc are not observed (see this issue for more details)Support matrix is mainly dependent on 2 advanced language features: Proxy
and Reflect
. The broader their adoption - the broader the support matrix of ObjectObserver.
0.2.1
Date
, Blob
, Number
, String
, Boolean
, Error
, SyntaxError
, TypeError
, URIError
, Function
, Promise
, RegExp
(see this issue for more details)0.2.0
pop
, shift
, splice
actions on arrays) and replaced (simple update on objects and arrays, fill
on arrays) observed sub-graphs are being revoked as wellpop
, shift
, splice
) are turned back to the plain object (yet having all of the changes done to the observable) when returned by APIs0.1.0
You have 2 ways to load the library: into a 'window' global scope, or a custom scope provided by you.
<script src="object-observer.js"></script>
<script>
var person = { name: 'Uriya', age: 8 },
observablePerson;
observablePerson = Observable.from(person);
</script>
var customNamespace = {},
person = { name: 'Nava', age: 6 },
observablePerson;
fetch('object-observer.js').then(function (response) {
if (response.status === 200) {
response.text().then(function (code) {
Function(code).call(customNamespace);
// the below code is an example of consumption, locate it in your app lifecycle/flow as appropriate
observablePerson = customNamespace.Observable.from(person);
});
}
});
Observable
static propertiesfrom
- receives a non-null object and returns Observable
interface:
var person = { name: 'Aya', age: '1' },
observablePerson;
observablePerson = Observable.from(person);
...
Observable
instance propertiesobserve
- receives a function, which will be added to the list of observers subscribed for a changes of this observable:
function personUIObserver(changes) {
changes.forEach(change => {
console.log(change.type);
console.log(change.path);
console.log(change.value);
console.log(change.oldValue);
});
}
...
observablePerson = Observable.from(person);
observablePerson.observe(personUIObserver);
Changes delivered always as an array. Changes MAY NOT be null. Changes MAY be an empty array. Each change is a defined, non-null object, having:
type
- one of the following: 'insert', 'update', 'delete', 'shuffle' or 'reverse'path
- path to the changed property represented as an Array of nodes (see examples below)value
- new value; not available in 'delete', 'shuffle' and 'reverse' changesoldValue
- old value; not available in 'insert', 'shuffle' or 'reverse' changesunobserve
- receives a function/s which previously was/were registered as an observer/s and removes it/them. If no arguments passed, all observers will be removed:
...
observablePerson.unobserve(personUIObserver);
...
observablePerson.unobserve();
...
revoke
- parameterless. All of the proxies along the observed graph will be revoked and thus become unusable. observe
and unobserve
methods will mimic the revoked Proxy
behaviour and throw TypeError
if used on the revoked Observable
. Subsequent revoke
invokations will have no effect:
...
observablePerson.revoke();
...
var order = { type: 'book', pid: 102, ammount: 5, remark: 'remove me' },
observableOrder;
observableOrder = Observable.from(order);
observableOrder.observe(changes => {
changes.forEach(change => {
console.log(change);
});
});
observableOrder.ammount = 7; // { type: 'update', path: ['ammount'], value: 7, oldValue: 5 }
observableOrder.address = { // { type: "insert", path: ['address'], value: { ... } }
street: 'Str 75',
apt: 29
};
observableOrder.address.apt = 30; // { type: "update", path: ['address','apt'], value: 30, oldValue: 29 }
delete observableOrder.remark; // { type: "delete", path: ['remark'], oldValue: 'remove me' }
var a = [ 1, 2, 3, 4, 5],
observableA;
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], oldValue: 5 }
// observableA = [ 1, 2, 3, 4 ]
// the 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' }
// { type: 'insert', path: [5], value: 'b' }
// observableA = [1, 2, 3, 4, 'a', 'b']
observableA.shift(); // { type: 'delete', path: [0], oldValue: 1 }
// observableA = [ 2, 3, 4, 'a', 'b' ]
// the 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' }
// { type: 'insert', path: [1], value: 'y' }
// observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.reverse(); // { type: 'reverse' }
// observableA = [ 'b', 'a', 4, 3, 2 ]
observableA.sort(); // { type: 'shuffle' }
// observableA = [ 2, 3, 4, 'a', 'b' ]
observableA.fill(0, 0, 1); // { type: 'update', path: [0], value: 0, oldValue: 2 }
// 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 }
// { type: 'insert', path: [1], value: 'y' }
Arrays notes:
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 invokation, while leaving out the implicit outcomes like reindexing of the rest of the Array.FAQs
object-observer utility provides simple means to (deeply) observe specified object/array changes; implemented via native Proxy; changes delivered in a synchronous way
We found that object-observer demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.