在事件循环中,当函数运行时,它是否真正同步? [关闭]

问题描述 投票:1回答:1

编辑以缩小问题范围。

假设在Node中调用异步函数apiLibrary.post(urlString,data,callback)并将其添加到事件循环中。它正在使用数据向URL发送发布请求。

一旦它实际在事件循环中运行,它是否同步等待响应?我有点困惑,但从我可以拼凑起来的东西,本身没有真正的异步代码这样的东西。异步代码意味着“我将在稍后同步运行此代码,即使在同步执行期间,我也必须等待。”

然后在以同步方式发出post请求之后,运行回调函数,其参数是来自urlString的外部服务器的返回值。

这是正确的,还是异步意味着“我将在以后运行此功能”?

javascript node.js asynchronous event-loop
1个回答
0
投票

P,哪里开始;-)

第1点:

由于apiLibrary函数调用尚未运行,因此响应变量在内存中声明,但未设置为任何值。因此,控制台日志在终端中显示未定义。然后它运行otherFunction,运行(在第2帧中)并完全正常返回(弹出第2帧,现在我们回到第1帧专用于makeCall),所有这些都是因为apiLibrary函数从未运行而仍未定义。

response var的值取决于async apiLibrary.post方法的实现方式。它可能不会返回任何内容,也可能会返回您的makeCall可能会等待的承诺。但你是对的,在makeCall执行过程中,它的价值不会改变。 apiLibrary.post的结果不会神奇地填充。

第2点:

“等一下,我即将关闭这个功能,但是有一个异步调用来自这个堆栈框架,我还没有去过,因为我从来没有在事件循环中运行代码而是在堆栈的这个框架中让我先跑吧。“

不。 apiLibrary.post调用将此调用放入Node的事件队列中,该队列由其事件循环处理。节点使用协作式多任务处理,因此不会中断同步执行功能。因此,您的makeTask将到达回调方法,使用未定义值的响应调用它,并且一旦回调返回,该方法退出。然后事件循环将从事件队列中弹出对apiLibrary.post的异步调用并执行它。在您的代码中,其结果可能会变成(数据中心)热量并永远丢失。

第3点:

此外,事件循环是否有自己的堆栈?代码的常规执行和事件循环中异步代码的执行都在同一个线程上运行,所以我认为这意味着它们使用相同的堆栈,并从相同的堆内存到达。

大概是的,因为Node是单线程的。如果你在函数中的某个地方放置一个断点并检查callstack,你会看到一堆框架级方法(在他们的名字中带有“tick”的一堆方法)。

第4点:

一旦Express中的路由被命中,考虑到Node现在正在处理一个函数,就会在常规循环或事件循环中添加一个函数。是谁在那里添加的?当它运行该函数,并有一些数据要res.send回到前端时,是发送函数同步还是异步?它本身并不是一个完整的I / O,因为它没有预期的响应,只是发送数据然后它就完成了该请求。

我不知道确切的完整细节,但让我试试:Express已经打开了一个端口,比如端口80,并且可能注册了数据到达时的处理程序方法。有了一些操作系统魔法,来自传入请求的数据传递到Node(进入缓冲区?),然后使用事件循环来调用Express,它知道你所有的路由,调用所有中间件并最终调用你的处理函数。 res.send调用与您的响应切换到操作系统的位置是同步的(类似的)。

希望这会让它更清晰一些。

第5点:

我的建议是,阅读更多关于在Node中异步编程的各种方法。我的印象是你还没有掌握回调式异步编程。只是学习如何使用它,担心堆栈和以后的东西。供您参考,这些是异步编程样式:

  1. 最古老,最丑陋的:回调。深度嵌套回调链,难以处理并且容易出错。
  2. 下一个最好的:承诺。承诺链保持平稳,使用异常进行结构化错误处理,并在承诺链末尾捕获“块”。
  3. Await和async:与“yield”功能相比,例如在C#中。最新最好的,使异步编程看起来像同步编程。但仍然有一堆陷阱可以介入。
© www.soinside.com 2019 - 2024. All rights reserved.