Skip to content

Instantly share code, notes, and snippets.

@Sceat
Last active June 9, 2020 19:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sceat/465b44a8e6c7e05dc8c173e809c08a12 to your computer and use it in GitHub Desktop.
Save Sceat/465b44a8e6c7e05dc8c173e809c08a12 to your computer and use it in GitHub Desktop.
EventIterator raw JS file translated from https://github.com/rolftimmermans/event-iterator
const noop = () => {}
export default class EventIterator {
#listen
#options
constructor(listen, options) {
this.#listen = listen
this.#options = {
highWaterMark: 100,
...options,
}
Object.freeze(this)
}
[Symbol.asyncIterator]() {
let pullQueue = []
const pushQueue = []
const listen = this.#listen
let remove = noop
let finaliser = 0
const push = value => {
const resolution = {
value,
done: false,
}
if (pullQueue.length)
pullQueue.shift()?.resolve(resolution)
else {
pushQueue.push(Promise.resolve(resolution))
const { highWaterMark } = this.#options
if (
highWaterMark !== undefined
&& pushQueue.length >= highWaterMark
)
console.log(`EventIterator queue reached ${ pushQueue.length } items`)
}
}
const stop = () => {
Promise.resolve().then(() => {
remove()
finaliser = {
value: undefined,
done : true,
}
if (pullQueue.length) {
for (const placeholder of pullQueue)
placeholder.resolve(finaliser)
pullQueue = []
} else pushQueue.push(Promise.resolve(finaliser))
})
}
const fail = error => {
Promise.resolve().then(() => {
remove()
if (pullQueue.length) {
for (const placeholder of pullQueue)
placeholder.reject(error)
pullQueue = []
} else {
const rejection = Promise.reject(error)
// Attach error handler
// to avoid leaking an unhandled promise rejection.
rejection.catch(() => {})
pushQueue.push(rejection)
}
})
}
remove
= listen({
push,
stop,
fail,
}) || remove
return {
async next() {
if (finaliser) return finaliser
else if (pushQueue.length) return pushQueue.shift()
return new Promise((resolve, reject) => {
pullQueue.push({
resolve,
reject,
})
})
},
async return() {
remove()
finaliser = {
value: undefined,
done : true,
}
return finaliser
},
}
}
}
{
"name": "event-iterator",
"version": "0.1.0",
"type": "module",
"main": "EventIterator.js"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment