AsyncHook 回调中的打印


【Printing in AsyncHook callbacks】

因为向控制台打印是一个异步操作,console.log() 会导致 AsyncHook 回调被调用。在 AsyncHook 回调函数中使用 console.log() 或类似的异步操作会导致无限递归。在调试时,一个简单的解决方法是使用同步的日志操作,例如 fs.writeFileSync(file, msg, flag)。这将把内容打印到文件中,并且不会递归调用 AsyncHook,因为它是同步的。

【Because printing to the console is an asynchronous operation, console.log() will cause AsyncHook callbacks to be called. Using console.log() or similar asynchronous operations inside an AsyncHook callback function will cause an infinite recursion. An easy solution to this when debugging is to use a synchronous logging operation such as fs.writeFileSync(file, msg, flag). This will print to the file and will not invoke AsyncHook recursively because it is synchronous.】

import { writeFileSync } from 'node:fs';
import { format } from 'node:util';

function debug(...args) {
  // Use a function like this one when debugging inside an AsyncHook callback
  writeFileSync('log.out', `${format(...args)}\n`, { flag: 'a' });
}const fs = require('node:fs');
const util = require('node:util');

function debug(...args) {
  // Use a function like this one when debugging inside an AsyncHook callback
  fs.writeFileSync('log.out', `${util.format(...args)}\n`, { flag: 'a' });
}

如果日志记录需要异步操作,可以使用 AsyncHook 本身提供的信息来跟踪导致异步操作的原因。当触发 AsyncHook 回调的是日志操作本身时,应跳过日志记录。通过这样做,可以打破原本无限的递归。

【If an asynchronous operation is needed for logging, it is possible to keep track of what caused the asynchronous operation using the information provided by AsyncHook itself. The logging should then be skipped when it was the logging itself that caused the AsyncHook callback to be called. By doing this, the otherwise infinite recursion is broken.】