Design async operations to prevent race conditions, memory leaks, and ensure proper resource cleanup. Key principles: 1. Avoid mutating shared state in async operations
Design async operations to prevent race conditions, memory leaks, and ensure proper resource cleanup. Key principles:
Example of problematic code:
// BAD: Mutating shared state in async context
Object.assign(socket, {
getPattern: () => this.reflectPattern(callback)
});
// BAD: Potential memory leak with async timing
this.routingMap.set(packet.id, callback);
await this.serialize(packet.data);
Better approach:
// GOOD: Maintain request-scoped state
class RequestContext {
constructor(private pattern: string) {}
getPattern() { return this.pattern; }
}
// GOOD: Ensure cleanup on unsubscribe
const cleanup = new AbortController();
try {
if (cleanup.signal.aborted) return;
const data = await this.serialize(packet.data);
this.routingMap.set(packet.id, callback);
cleanup.signal.addEventListener('abort', () => {
this.routingMap.delete(packet.id);
});
} catch (err) {
this.routingMap.delete(packet.id);
}
For streaming operations, use appropriate async scheduling:
// GOOD: Non-blocking stream processing
return from(items).pipe(
concatMap(item => defer(() => processItem(item))),
observeOn(asyncScheduler)
);
Enter the URL of a public GitHub repository