-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session Proposal: NodeJS Asynchronous Scheduling #392
Comments
Refs: nodejs/node#51471 |
Would love to attend this remotely or discuss offline |
Might be also relevant to make sure that the docs are correct: https://www.builder.io/blog/visual-guide-to-nodejs-event-loop |
Example of problem to discuss. import { EventEmitter } from 'events'
// Unhandled exception
setImmediate(async () => {
const e = await new Promise(resolve => {
const e = new EventEmitter()
resolve(e)
process.nextTick(() => {
e.emit('error', new Error('nextTick'))
})
})
e.on('error', () => {})
})
// Unhandled exception
setImmediate(async () => {
const e = await new Promise(resolve => {
const e = new EventEmitter()
resolve(e)
queueMicrotask(() => {
e.emit('error', new Error('queueMicrotask'))
})
})
e.on('error', () => {})
})
// OK, but slow
setImmediate(async () => {
const e = await new Promise(resolve => {
const e = new EventEmitter()
resolve(e)
setImmediate(() => {
e.emit('error', new Error('setImmediate'))
})
})
e.on('error', () => {})
}) Please don't get hung up the |
I'm wondering if it's possible to solve generically by adding the capability to emit an event after someone is listening to it to the abstraction itself - e.g. by providing a helper to defer emitting an event up to setImmediate if there are no existing listeners for it. This is similar to what we do for promises at the moment with unhanadled rejection detection. |
Can we toss into this topic, how are web platform APIs for managing asynchronicity like AbortController working for your needs in Node? Maybe that is too much of a tangent and can stick in the standards part, though. |
For the remote participants: we've scheduled Zoom Webinars for the sessions, please register using the links provided in #387 and you'll get a link in an email to join the sessions. More info in the issue mentioned. EDIT: You can also get invited to be a panelist beforehand to save the registration & promotion step. Ping in the OpenJS slack with your email or send a email to the email in my GitHub profile to get an invitation. |
A possible solution is to allow const events = require('events')
class EventEmitter extends events.EventEmitter {
constructor(options) {
super(options)
this.buffer = options?.bufferStrategy || new NoBufferStrategy()
}
emit(name, ...args) {
// No listeners yet. Try to buffer the event.
if (!this.listeners(name).length && this.buffer.buffer(name, args)) {
return
}
return super.emit(name, ...args)
}
on(name, ...args) {
try {
return super.on(name, ...args)
} finally {
// After attaching a handler, flush any buffered events.
this.buffer.flush(name, (...args) => {
this.emit(...args)
})
}
}
}
// Default strategy does no buffering.
class NoBufferStrategy {
buffer(name, task) {
return false
}
flush() {}
}
// A possible alternative strategy could buffer the events until a handler is given.
class BufferStrategy {
#buffered = new Map()
buffer(name, args) {
const map = this.#buffered
if (!map.has(name)) {
map.set(name, [])
}
map.get(name).push(args)
return true
}
flush(name, handle) {
const map = this.#buffered
const queue = map.get(name)
map.delete(name)
for (const args of queue) {
handle(name, ...args)
}
}
}
const p = new Promise((resolve) => {
const e = new EventEmitter({
bufferStrategy: new BufferStrategy()
})
process.nextTick(() => {
e.emit('error', 'nextTick')
})
resolve(e)
})
p.then(e => {
return new Promise(resolve => {
setImmediate(resolve, e)
})
}).then(e => {
e.on('error', (error) => console.log('error', error))
}) It's worth noting that the |
Closing as the session has ended. Links to the recordings:
Links to the notes (very inaccurate, we should try harder at getting dedicated note takers the next time): Drafted trip report, would appreciate some reviews. Expect to publish on the official blog next week: https://hackmd.io/5vvP8o5bTmqcbNh-3oHpag |
Proposal
Topic of the session
Existing pitfalls in NodeJS asynchronous scheduling and patterns.
nextTick
andqueueMicrotask
(Inconsistent behavior of nextTick and queueMicrotask nodejs/node#51156).Type of the session
Estimated duration of the session
Date and Time of the session
Level
Pre-requisite knowledge
Describe the session
Session facilitator(s), Github handle(s) and timezone(s)
Meeting notes and Virtual Meeting Link
Follow-up / Set-up sessions (if any)
Additional context (optional)
The text was updated successfully, but these errors were encountered: