Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
'use strict';
const {
AsyncResource,
executionAsyncId,
createHook,
} = require('async_hooks');
const EventEmitter = require('events');
const util = require('util');
const HasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
const zones = new Map();
class Zone extends EventEmitter {
#spec;
#resource;
#report;
constructor({ name = null, spec = {} } = {}) {
super();
this.name = name;
this.#spec = spec;
this.#resource = new AsyncResource('ZONE', {
triggerAsyncId: executionAsyncId(),
requireManualDestroy: false,
});
zones.set(this.#resource.asyncId(), this);
}
run(fn, thisArg, ...args) {
let r;
try {
r = this.#resource.runInAsyncScope(fn, thisArg, ...args);
if (r instanceof Promise) {
r.catch((err) => {
this.emit('error', err);
});
}
} catch (err) {
this.emit('error', err);
}
return r;
}
get(name) {
return HasOwnProperty(this.#spec, name) ? this.#spec[name] : undefined;
}
fork({ name, spec } = {}) {
const z = new Zone({
name,
spec: {
...spec,
...this.#spec,
},
});
return z;
}
get parent() {
return zones.get(this.#resource.triggerAsyncId());
}
static get current() {
return zones.get(executionAsyncId());
}
[util.inspect.custom](depth, options) {
const O = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1,
});
return `Zone {
name => ${util.inspect(this.name, O)}
spec => ${util.inspect(this.#spec, O)} }`;
}
}
Zone.prototype[Symbol.toStringTag] = 'Zone';
zones.set(executionAsyncId(), new Zone());
createHook({
init: (asyncId, type, triggerAsyncId) => {
zones.set(asyncId, zones.get(triggerAsyncId));
},
destroy: (asyncId) => {
zones.delete(asyncId);
},
}).enable();
global.Zone = Zone;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.