Keep event handlers synchronous to prevent race conditions and timing issues. Async operations within event handlers can cause deadlocks, missed events, and unpredictable behavior.
Why this matters: Event handlers must execute synchronously to ensure proper event ordering and prevent race conditions. When async operations are introduced into event handlers, they can cause events to be missed, create deadlocks with message passing, or lead to cleanup operations happening at the wrong time.
Guidelines:
Example of problematic pattern:
// BAD: Async event handler can cause timing issues
private async _onPage(page: Page): Promise<void> {
this._pages.add(page);
this.emit(Events.BrowserContext.Page, page);
await this._mockingProxy?.instrumentPage(page); // This breaks synchronous event flow
}
// BAD: Immediate cleanup prevents event delivery
close() {
this._socket.close();
eventsHelper.removeEventListeners(this._eventListeners); // Client never receives 'close' event
}
Better approach:
// GOOD: Keep handler synchronous, defer async work
private _onPage(page: Page): void {
this._pages.add(page);
this.emit(Events.BrowserContext.Page, page);
// Schedule async work separately
this._instrumentPageAsync(page);
}
private async _instrumentPageAsync(page: Page) {
await this._mockingProxy?.instrumentPage(page);
}
This principle prevents deadlocks, ensures event ordering, and maintains predictable async behavior throughout the application.
Enter the URL of a public GitHub repository