README
xo-collection
Generic in-memory collection with events
Install
Installation of the npm package:
> npm install --save xo-collection
Usage
var { Collection } = require('xo-collection')
Creation
// Creates a new collection.
var col = new Collection()
Manipulation
Inserting a new item
col.add('foo', true)
- Throws
DuplicateItem
if the item is already in the collection.
Updating an existing item
col.update('foo', false)
- Throws
NoSuchItem
if the item is not in the collection.
Inserting or updating an item
col.set('bar', true)
Notifying an external update
If an item is an object, it can be updated directly without using the
set
/update
methods.To make sure the collection stays in sync and the correct events are sent, the
touch
method can be used to notify the change.
var baz = {}
col.add('baz', baz)
baz.prop = true
col.touch('baz')
Because this is a much used pattern,
touch
returns the item to allow its direct modification.
col.touch('baz').prop = false
- Throws
NoSuchItem
if the item is not in the collection. - Throws
IllegalTouch
if the item is not an object.
Removing an existing item
col.remove('bar')
- Throws
NoSuchItem
if the item is not in the collection.
Removing an item without error
This is the symmetric method of set()
: it removes the item if it
exists otherwise does nothing.
col.unset('bar')
Removing all items
col.clear()
Query
Checking the existence of an item
var hasBar = col.has('bar')
Getting an existing item
var foo = col.get('foo')
// The second parameter can be used to specify a fallback in case the
// item does not exist.
var bar = col.get('bar', 6.28)
- Throws
NoSuchItem
if the item is not in the collection and no fallback has been passed.
Getting a read-only view of the collection
This property is useful for example to iterate over the collection or to make advanced queries with the help of utility libraries such as lodash.
var _ = require('lodash')
// Prints all the items.
_.forEach(col.all, function (value, key) {
console.log('- %s: %j', key, value)
})
// Finds all the items which are objects and have a property
// `active` which equals `true`.
var results = _.where(col.all, { active: true })
Getting the number of items
var size = col.size
Events
The events are emitted asynchronously (at the next turn/tick of the event loop) and are deduplicated which means, for instance, that an addition followed by an update will result only in a single addition.
New items
col.on('add', added => {
forEach(added, (value, key) => {
console.log('+ %s: %j', key, value)
})
})
Updated items
col.on('update', updated => {
forEach(updated, (value, key) => {
console.log('± %s: %j', key, value)
})
})
Removed items
col.on('remove', removed => {
// For consistency, `removed` is also a map but contrary to `added`
// and `updated`, the values associated to the keys are not
// significant since the items have already be removed.
forEach(removed, (value, key) => {
console.log('- %s', key)
})
})
End of update
Emitted when all the update process is finished and all the update events has been emitted.
col.on('finish', () => {
console.log('the collection has been updated')
})
Iteration
for (const [key, value] of col) {
console.log('- %s: %j', key, value)
}
for (const key of col.keys()) {
console.log('- %s', key)
}
for (const value of col.values()) {
console.log('- %j', value)
}
Views
const { View } = require('xo-collection/view')
A view is a read-only collection which contains only the items of a parent collection which satisfy a predicate.
It is updated at most once per turn of the event loop and therefore can be briefly invalid.
const myView = new View(parentCollection, function predicate(value, key) {
// This function should return a boolean indicating whether the
// current item should be in this view.
})
Contributions
Contributions are very welcomed, either on the documentation or on the code.
You may:
- report any issue you've encountered;
- fork and create a pull request.