npm package: @shmish/observable
Description: ESM ES observable module, for personal use
Author: Shmish
Latest version: 1.4.0

# @shmish/observable

- **author**: Shmish &lt;shmish90@gmail.com>
- **license**: MIT

```npm install @shmish/observable --save```

# Usage

## Observable
An observable is an object that represents a collection of values arriving syncrounously or asyncrounously.  Using this constructor directly is not recomended unless absolutly nessasarry.  In practice, it is almost always better to use one of the static creation methods such as `Observable.fromEvent` and `Observable.of` 

```javascript 
// Example
const myObservable = new Observable(observer => {
  setInterval(observer.next, 1000, 'some data')
})
```

### Observable.of(...args)
`Observable.of` takes any number of arguments and returns a new `Observable` collection of the arguments (in order).
```javascript
// Example
const myFirstObservable = Observable.of(2, 4, 6)
const mySecondObservable = Observable.of('hello', 3, 56, 0x10)
```

### Observable.from(iterable)
`Observable.from` takes a single iterable as an argument, such as a `String`, `Array`, or `Generator` and returns a new `Observable` collection of the itterable argument.
```javascript
// Example
const myFirstObservable = Observable.from([1, 2, 4])
const MySecondObservable = Observable.from('hello world')
```

### Observable.fromEvent(emiter, ...events)
`Observable.fromEvent` takes an event emitter (implements `on` or `addEventListener`) and any number of events to subscribe to.  The `Observable` will automaticly notify any attached observers when an event is triggered.
```javascript
// Example
const $button = document.getElementById('button')
const clickStream = Observable.fromEvent($button, 'click', 'touch')
```

### Observable.prototype.subscribe(observer | [functions])
`Observable.prototype.subscribe` takes either an `Observer` object or a `next`, `error`, and `complete` callback (in that order).  `.subscribe` returns a `Subscription` object, representing the data channel between the `Observable` collection and the `Observer`
```javascript
// Example: callbacks
const subsription = Observable.of(1, 2, 3).subscribe(
  val => console.log(val),     // Next
  err => console.error(err),   // Error
  () => console.log('done')    // Complete
)

//=> 1
//=> 2
//=> 3
//=> 'done'
```
```javascript
// Example: Observer
// Note: all overrides are optional
class Logger extends Observer {
  next (val) { console.log(val) }  // Override 'next' method
  error (err) { console.error(err) }  // Override 'error' method
  complete () { console.log('done') }  // Override 'complete' method
}

const subscription = Observable.of(1, 2, 3).subscribe(new Logger())

//=> 1
//=> 2
//=> 3
//=> 'done'
```

### Observable.prototype.map(functor)
The `Observable.prototype.map` method creates a new `Observable` with the results of calling the provided function on each value passing through the calling `Observable`
```javascript
// Example
const subscription = Observable.of(1, 2, 3)
  .map(x => x ** 2)
  .map(x => x - 1)
  .subscribe(x => console.log(x))

//=> 0
//=> 3
//=> 8


// Another example
const subscription = Observable.from('hello')
  .map(c => c.toUpperCase())
  .subscribe(c => console.log(c))

//=> 'H'
//=> 'E'
//=> 'L'
//=> 'L'
//=> 'O'
```

### Observable.prototype.filter(functor)
The `Observable.prototype.filter` method creates a new `Observable` with all the elements that pass the test of the provided function
```javascript
// Example
const subscription = Observable.of(1, 2, 3, 4)
  .filter(x => x % 2 === 0)
  .subscribe(x => console.log(x))

//=> 2
//=> 4
```

### Observable.prototype.reduce(functor, [initial])
The `Observable.prototype.reduce` method return a `Promise` of the value resulting from applying the provided function against an accumulatorand each element passing throught the observable.  The function takes the form of `(accumulator, value) => newVal`
```javascript
// Example
const myPromise = Observable.of(1, 2, 3)
  .reduce((acc, val) => acc + val)

//=> Promise {val: 6}

// Another example
Observable.of(1, 2, 3)
  .reduce((acc, val, i) => acc + val + i)  // Here, an optional index param is passed
  .then(x => console.log(x))

//=> 9
```

### Observable.prototype.wait(delayMS)
The `Observable.prototype.wait` method produces a new `Observable` that 'holds' values for a provided delay before parring them on.
```javascript
// Example
Observable.of(1, 2, 3)
  .wait(200)
  .subscribe(x => console.log(x))
```