You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was thinking the core of this could be simplified quite a bit, with some redundant bits removed and/or moved to helper functions:
emitter = new Emitter(t => ({emit, resolve, reject})) - Create an emitter with an initializer callback.
Each returned hook accepts values received from that method. It can choose to either delegate them, ignore them, or whatever.
By default, missing hooks delegate, and if the return value isn't an object, only default hooks are used.
emitter = new Emitter() - Create a simple emitter.
This is just sugar for new Emitter(() => {}).
t.emit(value) - Emit a value from this emitter.
t.resolve(value) - Resolve the emitter.
t.reject(value) - Reject the emitter.
emitter.emit(value) - Send an emit to this emitter.
emitter.resolve(value) - Send a stream resolution and stop sending values to emitter hooks.
emitter.reject(value) - Reject the emitter and stop sending values to emitter hooks.
emitter.link({emit, resolve, reject}) - Lets you listen for values emitted, resolving when the emitter resolves and rejecting when it rejects. Returns the argument for convenience with the constructor.
Composition would simply be function composition in this case.
By design, all emitters would be hot. This works like event emitters and subscriptions, but not observables. If an emitter wants to know when it's resolved, it can just invoke emitter.then on the return value.
Here's the things I removed:
Variadic each - just use .each repeatedly. Same effect
The second and third parameters to each callbacks - this aligns with iterators that lack this
Inheritance from Promise. It implements multicast internally and synchronously propagates errors and completion. Async closure does pose certain usability issues with observables, BTW, and I'd like that to not be forgotten.
A polyfill would be relatively straightforward:
// privateconstnoError={}classEmitterProxy{constructor(emitter){this._=emitter// A set is used so it keeps its place if a callback is removed// during iteration.this._subs=newSet()this._hooks=null}send(value){if(this._canEmit()){for(constsubofthis._data._subs){if(!this._canEmit())breaksub.send(value)}}}resolve(value){this._close("resolved","resolve")}reject(value){this._close("rejected","reject")}_canEmit(){returnthis._!=null}_close(state,method){if(this._canEmit()){constsubs=this._subsconsthooks=this._hooksconstparent=this._parentthis._._state=statethis._._data=valuethis._=this._subs=this._hooks=nullleterror=noErrorfor(constsubofsubs){try{sub[method](value)}catch(e){error=e}}if(error!==noError)throwerror}}}// publicclassEmitter{constructor(init){this._state="open"this._data=newEmitterProxy(this)if(init!=null){try{constresult=init(this._data)if(this._state==="open"&&result!=null&&(typeofresult==="object"||typeofresult==="function")){this._data._hooks=result}}catch(e){if(this._state==="open")this._data.reject(e)}}}send(value){if(this._state==="open"){consthooks=this._data._hooksif(hooks!=null&&typeofhooks.emit==="function"){hooks.emit(value)}else{this._data.send(value)}}}resolve(value){if(this._state==="open"){consthooks=this._data._hooksthis._state="half closed"this._data._hooks=nullif(hooks!=null&&typeofhooks.resolve==="function"){hooks.resolve(value)}else{this._data.resolve(value)}}}reject(value){if(this._state==="open"){consthooks=this._data._hooksthis._state="half closed"this._data._hooks=nullif(hooks!=null&&typeofhooks.reject==="function"){hooks.reject(value)}else{this._data.reject(value)}}}link(sub){switch(this._state){case"open": case"half closed": this._data._subs.add(sub);breakcase"resolved": sub.resolve(this._data);breakcase"rejected": sub.reject(this._data);break}returnsub}}
The text was updated successfully, but these errors were encountered:
I was thinking the core of this could be simplified quite a bit, with some redundant bits removed and/or moved to helper functions:
emitter = new Emitter(t => ({emit, resolve, reject}))
- Create an emitter with an initializer callback.emitter = new Emitter()
- Create a simple emitter.new Emitter(() => {})
.t.emit(value)
- Emit a value from this emitter.t.resolve(value)
- Resolve the emitter.t.reject(value)
- Reject the emitter.emitter.emit(value)
- Send an emit to this emitter.emitter.resolve(value)
- Send a stream resolution and stop sending values to emitter hooks.emitter.reject(value)
- Reject the emitter and stop sending values to emitter hooks.emitter.link({emit, resolve, reject})
- Lets you listen for values emitted, resolving when the emitter resolves and rejecting when it rejects. Returns the argument for convenience with the constructor.emitter.run
, you could just use the pipeline operatorHere's how some of the operators would end up implemented, assuming the F# style was selected for the pipeline operator proposal:
Composition would simply be function composition in this case.
By design, all emitters would be hot. This works like event emitters and subscriptions, but not observables. If an emitter wants to know when it's resolved, it can just invoke
emitter.then
on the return value.Here's the things I removed:
each
- just use.each
repeatedly. Same effecteach
callbacks - this aligns with iterators that lack thisPromise
. It implements multicast internally and synchronously propagates errors and completion. Async closure does pose certain usability issues with observables, BTW, and I'd like that to not be forgotten.A polyfill would be relatively straightforward:
The text was updated successfully, but these errors were encountered: