0.1.6 add isEmitter function

add makeObserver and have addObserver call it, allows making without storing to all combination
add save argument for subscribe which will save to list for easy subscribe.
master
David Kebler 2020-01-16 22:16:35 -08:00
parent 63566d624f
commit 2497321c66
3 changed files with 42 additions and 17 deletions

View File

@ -6,7 +6,7 @@ let emitter = new EventEmitter()
// let verbose = process.env.VERBOSE==='true' // let verbose = process.env.VERBOSE==='true'
let combo = false let combo = true
// handler: (r)=> console.log('result:',r) // handler: (r)=> console.log('result:',r)
@ -74,11 +74,19 @@ if (combo) {
) )
if (combo){ if (combo){
console.log('a combination of e and pr was made\n','combinations are not added to \'all\' list')
console.log('subscribing to sub combination e, pr') console.log('subscribing to sub combination e, pr')
example.subscribe('combo',val => console.log('combo e, pr is:',val)) example.subscribe('combo',val => console.log('combo e, pr is:',val))
} }
} }
let madeonly = example.makeObserver('madeonly')
console.log('observer \'madeonly\' was only made and was not added so not in list \n',madeonly)
console.log('list of observers made and added to the all combination\n',example.observerNames)
emitter.emit('ec',{ready:true}) emitter.emit('ec',{ready:true})
emitter.emit('pe','yup') emitter.emit('pe','yup')
emitter.emit('e') emitter.emit('e')

View File

@ -1,6 +1,6 @@
{ {
"name": "@uci-utils/ready", "name": "@uci-utils/ready",
"version": "0.1.5", "version": "0.1.6",
"description": "A Class to Observe the reduced to boolean combined state of a map of observables", "description": "A Class to Observe the reduced to boolean combined state of a map of observables",
"main": "src/ready.js", "main": "src/ready.js",
"scripts": { "scripts": {

View File

@ -10,7 +10,7 @@ import { createBoolean } from '@uci-utils/to-boolean'
class Ready extends Map { class Ready extends Map {
constructor(opts) { constructor(opts) {
super(opts.observables) super(opts.observables)
this.emitter = typeof opts.emitter.on ==='function' ? opts.emitter : null this.emitter = isEmitter(opts.emitter) ? opts.emitter : null
const toBool = createBoolean(opts.boolean) // e.g. {undefined:true} const toBool = createBoolean(opts.boolean) // e.g. {undefined:true}
this.condition = opts.condition || ( (ev) => toBool(ev) ) this.condition = opts.condition || ( (ev) => toBool(ev) )
this.subscriptions = new Map() this.subscriptions = new Map()
@ -70,17 +70,17 @@ class Ready extends Map {
}) })
} }
addObserver(name, obs, opts={} ) { makeObserver(obs, opts={}) {
// validation and defaults, obs can be emitter, osbserver, or promise // validation and defaults, obs can be emitter, osbserver, or promise
if (!name || typeof(name)!=='string') return false // name required
if (isPlainObject(obs)) { opts = obs; obs=null } if (isPlainObject(obs)) { opts = obs; obs=null }
if (!(obs || this.emitter)) return false // some observable requried if (!(obs || this.emitter)) return false // some observable requried
let { condition, event, details } = opts let { condition, event, name} = opts
condition = condition || this.condition condition = condition || this.condition
if (typeof (obs ||{}).on ==='function') obs = fromEvent(obs, event || name) // it's an emitter if (isEmitter(obs) && (event || name)) obs = fromEvent(obs, event || name ) // it's an emitter
if (isPromise(obs)) obs = from(obs) // it's a promise if (isPromise(obs)) obs = from(obs) // it's a promise
if (obs && !isObservable(obs) && typeof obs==='function' && arguments.length===2) condition = obs if (obs && !isObservable(obs) && typeof obs==='function' && arguments.length===2) condition = obs
if (!obs && this.emitter) obs = fromEvent(this.emitter,event || name) if (!obs && this.emitter && (event || name)) obs = fromEvent(this.emitter,event || name)
if (!obs || !isObservable(obs)) return false if (!obs || !isObservable(obs)) return false
let xobs = obs.pipe( let xobs = obs.pipe(
tap(val => this.log(`${name} emitted/resolved the value =>${JSON.stringify(val)}`)), tap(val => this.log(`${name} emitted/resolved the value =>${JSON.stringify(val)}`)),
@ -88,17 +88,27 @@ class Ready extends Map {
tap(val => this.log(`boolean: ${val}`)), tap(val => this.log(`boolean: ${val}`)),
startWith(false), startWith(false),
shareReplay(1), shareReplay(1),
// multicast(new Subject())
) )
let sub = xobs.subscribe() xobs._readyType = true
this.set(name, {obs:xobs, sub:sub})
this.setObserverDetails(name,details)
this.combineObservers('__all__') // update total combo
if (this.subscriptions.has('__all__')) this.subscribe() // will resubscribe
return xobs return xobs
} }
combineObservers(name,list) { addObserver(name, obs, opts={} ) {
// validation and defaults, obs can be emitter, osbserver, or promise
if (!name || typeof(name)!=='string') return false // name required
opts.name = name
if (!(obs || {})._readyType) obs = this.makeObserver(obs, opts)
if (!isObservable(obs)) return false
let { details } = opts
let sub = obs.subscribe()
this.set(name, {obs:obs, sub:sub})
this.setObserverDetails(name,details)
this.combineObservers('__all__',opts) // update total combo
if (this.subscriptions.has('__all__')) this.subscribe() // will resubscribe
return obs
}
// TODO add option for whether changed is enabled (default) or not and store with combo for remake
combineObservers(name,list,opts={}) {
if (Array.isArray(name)) {list = name; name = null} if (Array.isArray(name)) {list = name; name = null}
name = name || '__all__' name = name || '__all__'
if (name==='__all__') list = Array.from(this.keys()) // get list of all observers if (name==='__all__') list = Array.from(this.keys()) // get list of all observers
@ -136,7 +146,7 @@ class Ready extends Map {
this.subscribe() // resubscribe to changed combo this.subscribe() // resubscribe to changed combo
} }
subscribe(name, handler) { subscribe(name, handler, save) {
// only one subscription at a time per observer or combination from this method // only one subscription at a time per observer or combination from this method
if (typeof name ==='function') { if (typeof name ==='function') {
handler=name handler=name
@ -148,7 +158,7 @@ class Ready extends Map {
if (!obs) return false if (!obs) return false
if (this.subscriptions.has(name)) this.subscriptions.get(name).subs.unsubscribe() if (this.subscriptions.has(name)) this.subscriptions.get(name).subs.unsubscribe()
let subs = obs.subscribe(handler) let subs = obs.subscribe(handler)
this.subscriptions.set(name,{subs:subs,handler:handler}) if (save) this.subscriptions.set(name,{subs:subs,handler:handler})
return subs return subs
} }
@ -179,7 +189,14 @@ function map(fn) {
return isAsync(fn) ? switchMap.call(this,fn) : simpleMap.call(this,fn) return isAsync(fn) ? switchMap.call(this,fn) : simpleMap.call(this,fn)
} }
function isEmitter(emitter) {
if (!emitter) return false
let check = ['on','emit']
return check.reduce((acc,fn)=> acc && typeof emitter[fn] ==='function',true)
}
function isAsync(fn) { function isAsync(fn) {
if (typeof fn !== 'function') return false
return (isPromise(fn) || fn.constructor.name === 'AsyncFunction') return (isPromise(fn) || fn.constructor.name === 'AsyncFunction')
} }