图解Node.js之async_hooks

本文介绍Node.js中async_hooks API的基本用法,包括如何利用init、before、after及destroy等回调函数追踪资源,以及如何自定义resource。此外,还探讨了如何使用on-async-hook进行事件跟踪。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次翻译,还好文章不长-_-|| 原文地址:async_hooks in node.js, illustrated

async_hooks,即异步钩子,是Node 8中一个新的实验性API。几周前我就注意到这个API,所以想看看这个API到底能帮我做些什么。

1. async_hooks基本用法

async_hooks API 能使我们追踪资源(resource)变得更加简单,只需要使用init、before、after、destroy这些回调函数去初始化 async_hooks 接口。

var asyncHooks = require('async_hooks')
var hooks = {
  init: init,
  before: before, 
  after: after,
  destroy: destroy
}
var asyncHook = asyncHooks.createHook(hooks)

通过createHook、enable、disable方法可以创建async_hooks、开始追踪、停止追踪:
这里写图片描述

async_hooks 基于一种resource的概念,一个resource会触发上面提到的async_hooks的回调函数。这种resource可以是TTYWRAP 、SSLCONNECTION 或者任何使用 Embedder API 定义的内容(稍后会提到)。如果要使用 http.createServer() 创建一个 server,我们可以看看async_hooks API的init回调函数的resource,代码如下:

var asyncHooks = require('async_hooks')
var http = require('http')
var fs = require('fs')

var hooks = {
  init: init
}
var asyncHook = asyncHooks.createHook(hooks)
asyncHook.enable()

http.createServer(function (req, res) {
  res.end('hello qts')
}).listen(8079)

function init (asyncId, type, triggerId) {
    fs.writeSync(1, `${type} \n`)
}

结果如下:
这里写图片描述

2. function init (asyncId, type, triggerId) {}

async_hooks init callback :
async_hooks init callback

init回调函数或许是最有趣的一个回调,它允许我们访问当前resource(current resource),并看看是什么原因触发了它。这就意味着我们最终能创建一个良好的结构来查看我们的应用程序中到底发生了什么。
这里写图片描述

我认为这是一个很棒的trace跟踪方法 : 在init中拿到 asyncId 和 triggerId,启动一个计时器去跟踪一些操作,最后在destroy回调中销毁计时器。按照这个思路,我写了一个 on-async-hook,一个简单的async_hook跟踪事件发射器。

当async_hooks调用init回调函数时,on-async-hook会创建一个trace跟踪,并且根据他们的triggerId来组合 resource。我想给操作计时,因此 on-async-hook 的跟踪结构还包含了开始时间和结束时间,也就是在init、destroy中进行添加和销毁计时器。一个简单的使用 on-async-hook 进行跟踪的结果如下:

这里写图片描述

3. Embedder API

如果要绑定本地的C++代码,则可能需要自定义resource,这一点可以使用Node 8 提供的实验性 Embedder API 做到。下面是一个例子,使用的是utp-native

var AsyncResource = require('async_hooks').AsyncResource
var utp = require('utp-native')
var resource = new AsyncResource('UTPNative')
var server = utp.createServer(function (socket) {
  socket.pipe(socket)
})
server.listen(1337, function () {
  var socket = utp.connect(1337)
  resource.emitBefore()
  socket.write('hello qts')
  resource.emitAfter()
  socket.on('data', function (data) {
    console.log('resourceId', resource.asyncId())
    console.log('triggerAsyncId', resource.triggerAsyncId())
    console.log('this is my data ', data)
  })
})
server.on('close', function () {
  resource.emitDestroy()
})

4. 展望

async_hooks仍然是一个实验性很强的API,它在接下来的时间中可能会不断变化,比如async_hooks.currentId()变成了async_hooks.executionAsyncId() ,但它能为我们提供一种新方法去监视程序,这点就非常炫酷了!

参考链接:
async_hooks in node.js, illustrated
on-async-hook

我按照上面说的在终端执行npm install express multer mysql cors --save时出现了如下报错:npm error code EPERM npm error syscall mkdir npm error path D:\myApps\Node.js\node_cache\_cacache npm error errno -4048 npm error Error: EPERM: operation not permitted, mkdir 'D:\myApps\Node.js\node_cache\_cacache' npm error at async mkdir (node:internal/fs/promises:857:10) npm error at async Object.insert (D:\myApps\Node.js\node_modules\npm\node_modules\cacache\lib\entry-index.js:124:5) npm error at async CacheEntry.store (D:\myApps\Node.js\node_modules\npm\node_modules\make-fetch-happen\lib\cache\entry.js:308:7) npm error at async fetch (D:\myApps\Node.js\node_modules\npm\node_modules\make-fetch-happen\lib\fetch.js:98:7) npm error at async RegistryFetcher.packument (D:\myApps\Node.js\node_modules\npm\node_modules\pacote\lib\registry.js:90:19) npm error at async RegistryFetcher.manifest (D:\myApps\Node.js\node_modules\npm\node_modules\pacote\lib\registry.js:128:23) npm error at async #fetchManifest (D:\myApps\Node.js\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:1202:20) npm error at async #nodeFromEdge (D:\myApps\Node.js\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:1040:19) npm error at async #buildDepStep (D:\myApps\Node.js\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:904:11) npm error at async Arborist.buildIdealTree (D:\myApps\Node.js\node_modules\npm\node_modules\@npmcli\arborist\lib\arborist\build-ideal-tree.js:181:7) { npm error errno: -4048, npm error code: 'EPERM', npm error syscall: 'mkdir', npm error path: 'D:\\myApps\\Node.js\\node_cache\\_cacache', npm error requiredBy: '.' npm error } npm error npm error The operation was rejected by your operating system. npm error It's possible that the file was already in use (by a text editor or antivirus), npm error or that you lack permissions to access it. npm error npm error If you believe this might be a permissions issue, please double-check the npm error permissions of the file and its containing directories, or try running npm error the command again as root/Administrator. npm error Log files were not written due to an error writing to the directory: D:\myApps\Node.js\node_cache\_logs npm error You can rerun the command with `--loglevel=verbose` to see the logs in your terminal 这是什么原因,如何解决
03-19
<think>好的,我现在需要帮用户解决在运行 `npm install` 时遇到的权限问题。首先,用户提供了详细的错误信息,看起来是EPERM错误,系统拒绝创建目录。我需要逐步分析可能的原因和解决方案。 首先,错误信息提到操作被操作系统拒绝,可能的原因包括文件被其他程序占用、权限不足,或者防病毒软件拦截。常见的解决方法是检查权限、关闭可能占用文件的程序、以管理员身份运行命令,或者调整npm的缓存目录。 我应该先建议用户以管理员身份运行终端,因为Windows下有些目录需要管理员权限才能写入。如果这样解决了问题,那说明是权限不足导致的。如果不行,可能需要检查是否有程序占用了该目录,比如资源管理器、编辑器或者杀毒软件。建议用户关闭这些程序再试。 另外,用户可能没有正确配置npm的缓存目录,或者目录权限有问题。可以指导用户修改npm的缓存目录到有权限的位置,比如使用`npm config set cache`命令。同时,检查Node.js安装目录的权限,确保用户有完全控制权。 还有一种可能是缓存损坏,需要清除npm缓存。用户可能运行过旧的缓存导致问题,建议使用`npm cache clean --force`清理缓存后再安装。 如果上述方法都无效,可能需要考虑重新安装Node.js,并确保安装路径没有空格或特殊字符,比如用户当前的路径是D:\myApps\Node.js,这里的空格可能会引起问题,但通常Node.js处理得还不错,不过也有可能,所以建议安装到简单路径如D:\NodeJS。 最后,提醒用户检查防病毒软件或防火墙是否拦截了npm的操作,临时禁用后再尝试安装。 总结下来,解决步骤应该是:以管理员身份运行、关闭占用程序、调整缓存目录、检查文件夹权限、清除缓存、检查杀毒软件、重新安装Node.js。需要分步骤解释,确保用户能逐步排查问题。</think>遇到此问题的原因主要是权限不足或文件被占用,以下是分步解决方案: $$ \text{错误类型:EPERM (Operation not permitted)} $$ **1. 以管理员身份运行终端** - 右键点击命令提示符/PowerShell/终端 - 选择"以管理员身份运行" - 重新执行安装命令: ```bash npm install express multer mysql cors --save ``` **2. 检查文件夹权限** - 打开路径 `D:\myApps\Node.js\node_cache` - 右键点击 `_cacache` 文件夹 → 属性 → 安全 - 点击"编辑" → 选择当前用户 → 勾选"完全控制" - 应用设置后重试 **3. 关闭占用程序** - 关闭所有正在使用该目录的程序(如VSCode、WebStorm、文件资源管理器) - 临时禁用杀毒软件(特别是实时文件保护功能) **4. 修改npm缓存路径(推荐)** ```bash npm config set cache "D:\myApps\Node.js\node_cache" --global npm config set prefix "D:\myApps\Node.js" --global ``` 验证配置: ```bash npm config get cache ``` **5. 清除缓存后重试** ```bash npm cache clean --force npm install express multer mysql cors --save ``` **6. 终极解决方案** 若仍失败,建议: - 卸载并重新安装Node.js - 选择安装路径时避免空格和特殊字符(如改为 `D:\NodeJS`) - 安装时勾选"Automatically install the necessary tools"选项 **数学关系说明**: $$ \text{解决概率} = 1 - \prod_{i=1}^{n}(1 - p_i) $$ 其中 $p_i$ 表示每个解决方案的有效概率,通过叠加使用上述方法可显著提高成功率。 建议按照顺序尝试上述方案,通常前3步即可解决90%以上的同类问题。若涉及公司环境,可能需要联系IT部门调整组策略权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值