How do I get the internal id of a Node Timeout using the symbol without hardcoding a lookup index?

Viewed 71

When you create a timer in Node, you get the following object back:

Timeout {
  _called: false,
  _idleTimeout: 500,
  _idlePrev: [TimersList],
  _idleNext: [TimersList],
  _idleStart: 34,
  _onTimeout: [Function],
  _timerArgs: undefined,
  _repeat: null,
  _destroyed: false,
  [Symbol(unrefed)]: false,
  [Symbol(asyncId)]: 5,
  [Symbol(triggerId)]: 1 }

The actual numeric id of this timeout object is contained under the [Symbol(asyncId)] field. My problem is, how can I get a reference to this symbol in a non-hackish way? The only way I currently know of that will give me this object is Object.getOwnPropertySymbols(), but using a hardcoded index seems fragile as f:

$ node -p 't=setTimeout(()=>{}, 500); triggerSym=Object.getOwnPropertySymbols(t)[2];t[asyncId]'
67

Is there a less fragile way I can get a reference to this symbol to use for lookup?

1 Answers

You can absolutely use Object.getOwnPropertySymbols to list the symbols of the timer object and then iterate to find the one you want. In my opinion that is pretty ugly and basically the same as relying on an implementation detail or using a _foo private-ish property on an object.

Currently the main case I know of for public symbol usage in Node is with promisifyable functions, where users can use

const promisifySymbol = Symbol.for('nodejs.util.promisify.custom');

The Node timer docs have no mention of such symbols, so I would recommend not using these symbols.

If you do need the ID itself to handle serialization of the timer's info or something, the timer [Symbol.toPrimitive]() implementation returns the ID directly, or indirectly, e.g.

const timer = setTimeout(() => {}, 0);

console.log(timer[Symbol.toPrimitive]()); // explicit call
console.log(+timer); // implicit call
Related