在 ES6 中引入了异步函数 async/await
,它允许开发者以同步的方式编写异步代码。而在 ES12 中,异步函数的上下文管理得到了进一步的加强,使得代码编写更加简便,也更加易于维护。
异步函数的上下文问题
首先,让我们来看一下在异步函数中会存在什么样的上下文问题。
例如,我们希望在异步函数中保存一个计时器的值,然后在完成异步操作后输出它。我们可以尝试以下代码:
-- -------------------- ---- ------- ----- -------- ------ - --- ----- - -- -------------- -- - -------- -- ------ ----- --- ----------------- -- ------------------- ------- ------------------- -- - - -------
然而,我们会发现计数器的值始终为 0,即使等待了 5 秒。这是因为计时器回调函数是在异步函数的上下文之外执行的,所以无法访问到它的作用域。
为了解决这个问题,我们可以将计时器的回调函数封装在另外一个函数中,并将计数器作为参数传递进去。
-- -------------------- ---- ------- ----- -------- ------ - --- ----- - -- -------- ------------- - -------- - ------------------------ ------ ----- --- ----------------- -- ------------------- ------- ------------------- -- - - -------
现在我们成功地在异步函数里使用了计时器,并正确输出了计数器的值。
异步函数的上下文管理
然而,上面的代码显得有些冗余,还需要手动封装回调函数并传递参数。在 ES12 中,我们可以使用 AsyncLocalStorage
来更加简便地管理异步函数的上下文。
AsyncLocalStorage
可以让我们在异步函数之间传递数据,类似于全局变量,但是只在当前运行的异步函数中有效。
我们先安装 node:async_hooks
,它包含了 AsyncLocalStorage
:
npm install async_hooks
接着我们可以以下面的方式在异步函数中使用 AsyncLocalStorage
:
-- -------------------- ---- ------- ------ - ----------------- - ---- -------------- ----- ----------------- - --- -------------------- ----------------------- ------ - -- ----- -- -- - -------------- -- - ----- ----- - ----------------------------------- -- -- ---------------------------------- - ----- - -- -- ------ ----- --- ----------------- -- ------------------- ------- ------------------------------------------------- -- - ---
我们使用 asyncLocalStorage.run()
在异步上下文中创建了一个新的存储区域,并设置了一个初始值 { count: 0 }
。接着我们可以使用 asyncLocalStorage.getStore()
在存储区域中获取或者更新值。
需要注意的是,在异步函数运行期间,存储区域中的数据只有在通过 asyncLocalStorage.getStore()
获取到之后才能改变。因此,在每个访问存储区域的点,asyncLocalStorage.getStore()
返回的实例往往是不同的。
结论
ES12 中的 AsyncLocalStorage
让异步函数的上下文管理变得更加简便,使得代码编写更加简单,也更加易于维护。
通过运用 AsyncLocalStorage
,您可以避免在异步函数中频繁使用封装方法和传递参数的繁琐过程,而仅需要一个共享的全局存储区域即可。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67455964c1a23897ea922bb7