node.js 异步
Node.js 14 is out now, and with that release, it brings in Async Local Storage support. Now you might thing, "Meh, okay. Local storage has been around for awhile," but this time, it's different.
Node.js 14现在已经发布,在该版本中,它引入了异步本地存储支持。 现在您可能会说:“嗯,好吧。本地存储已经存在了一段时间,”但是这次有所不同。
For starters, this is the Node runtime we're talking about and not the browser. Thus, having a "localStorage" browser-like concept doesn't really make sense for Node. And the fact is, it is not the localStorage you're probably thinking of either. So what is it then?
首先,这是我们正在讨论的Node运行时,而不是浏览器。 因此,拥有像浏览器一样的“ localStorage”概念对Node而言并没有任何意义。 事实是,这也不是您可能要考虑的localStorage。 那是什么呢?
Consider a web server like Apache running PHP for hosting a website. When PHP receives a request from a client, your web server makes sure to spin off a new thread. It lets that thread manage all the resources, local variables, function call stack, and so on for that particular request. Simple and easy. But a problem arises with JavaScript.
考虑像Apache这样的Web服务器,该服务器运行PHP以托管网站。 当PHP接收到来自客户端的请求时,您的Web服务器将确保剥离新线程。 它使该线程可以管理该特定请求的所有资源,局部变量,函数调用堆栈等。 简单容易。 但是JavaScript会出现问题。
JavaScript is single threaded – that means you cannot have multiple threads of JS running together under a same parent process. But don't let that fool you – JS is as fast (even faster) as mature solutions like a Java backend in handling web server requests.
JavaScript是单线程的–这意味着您不能在同一父进程下同时运行JS的多个线程。 但是,请不要让您愚弄–在处理Web服务器请求时,JS与Java后端这样的成熟解决方案一样快(甚至更快)。
How does that happen? Well, that's something for another article. But the important thing here is that Node is single threaded, so you do not have the benefits of thread local storage. Thread local storage is nothing but variables and functions local to a particular thread - in our case, for handling a particular user on the webpage.
怎么发生的? 好吧,这是另一篇文章。 但是这里重要的是Node是单线程的 ,因此您没有线程本地存储的好处。 线程本地存储只不过是特定线程本地的变量和函数-在我们的例子中,是用于处理网页上的特定用户的。
Single thread is a problem in this case as Node keeps executing synchronous code in one go as long as it doesn't exhaust all synchronous operations in the event loop. Then it'll keep a check on events and callbacks and execute that code whenever necessary.
在这种情况下,单线程是一个问题,因为Node会一劳永逸地执行同步代码,只要它不会在事件循环中耗尽所有同步操作即可。 然后它将检查事件和回调,并在必要时执行该代码。
In Node, a simple HTTP request is nothing but an event fired by the http
library to the node to handle the request – hence it is asynchronous.
在Node中,一个简单的HTTP请求不过是http
库向该节点触发以处理该请求的事件-因此它是异步的。
Now let's say you want to associate some data with this asynchronous operation. How would you do that?
现在,假设您要将一些数据与此异步操作相关联。 你会怎么做?
Well, you can create some sort of "global" variable and assign your special data to it. Then, when another request comes from the same user, you can use the global variable to read whatever you had stored earlier.
好了,您可以创建某种“全局”变量,并为其分配特殊数据。 然后,当同一用户发出另一个请求时,您可以使用全局变量读取之前存储的内容。
But it would fail spectacularly when you have more than one request on hand as Node would not execute asynchronous code serially (of course, that's the definition of asynchronous!).
但是当您手头有多个请求时,它将失败,因为Node不会串行执行异步代码(当然,这就是异步的定义!)。
Let's consider this dummy code (assume Node runtime):
让我们考虑一下这个伪代码(假设Node运行时):
server.listen(1337).on('request', (req) => {
// some synchronous operation (save state)
// some asynchronous operation
// some asynchronous operation
})
Consider this sequence of events:
考虑以下事件序列:
Now what if you want to persist specific data with that specific user whenever the asynchronous code specific to them is being called? Here's when you use AsyncStorage – storage for asynchronous flows in Node.
现在,如果您希望在调用特定于他们的异步代码时与该特定用户保持特定数据怎么办? 这是使用AsyncStorage的时候–在Node中存储异步流。
Consider this example straight from the official docs:
直接从官方文档考虑以下示例:
const http = require('http');
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
function logWithId(msg) {
const id = asyncLocalStorage.getStore();
console.log(`${id !== undefined ? id : '-'}:`, msg);
}
let idSeq = 0;
http.createServer((req, res) => {
asyncLocalStorage.run(idSeq++, () => {
logWithId('start');
// Imagine any chain of async operations here
setImmediate(() => {
logWithId('finish');
res.end();
});
});
}).listen(8080);
http.get('http://localhost:8080');
http.get('http://localhost:8080');
// Prints:
// 0: start
// 1: start
// 0: finish
// 1: finish
This example is showing nothing but the "stickyness" of the idSeq
with the respective request. You can imagine how express populates the req.session
object with the correct user every time. In a similar fashion, this is a low level API using a lower level construct in Node called async_hooks
which is still experimental, but is pretty cool to know!
此示例仅显示idSeq
与相应请求的“粘性”。 您可以想象每次express如何用正确的用户填充req.session
对象。 以类似的方式,这是一个低级API,它在Node中使用了一个较低级的结构async_hooks
,该结构仍处于试验阶段,但知道起来很酷!
Before you try to roll this out in production, beware – this is not something I would really recommend anybody do if not absolutely needed. This is because it comes with a non-negligible performance hit on your application. This is primarily because the underlying API of async_hooks
is still a WIP, but the situation should improve gradually.
在尝试将其投入生产之前,请当心–如果不是绝对需要的话,我不建议任何人这样做。 这是因为它给您的应用程序带来了不可忽视的性能影响。 这主要是因为async_hooks
的基础API仍然是WIP,但是这种情况应该逐渐改善。
That's basically it! A very simple brief introduction to what AsyncStorage is in Node 14 and what's the high level overall idea for it. If you want to learn all about new features in Node.js, check out this video:
基本上就是这样! 一个简单的简短介绍,介绍Node 14中的AsyncStorage以及它的高层总体思路。 如果您想全面了解Node.js的新功能,请观看以下视频:
Also, if you're an early adopter, try out codedamn – a platform for developers to learn and connect. I've been rolling out some sweet features there for you to try! Stay tuned.
另外,如果您是早期采用者,请尝试Codedamn –一个供开发人员学习和联系的平台。 我一直在那里推出一些不错的功能供您尝试! 敬请关注。
Peace!
和平!
翻译自: https://www.freecodecamp.org/news/async-local-storage-nodejs/
node.js 异步