当前位置: 首页 > 面试题库 >

为什么Node.JS中的函数和回调没有阻塞?

广楚
2023-03-14
问题内容

对Node的新手理解是,如果我重新编写同步代码或内联代码以利用函数/回调,则可以确保我的代码是非阻塞的。我很好奇这在事件堆栈方面的工作原理。
是它将阻塞:

var post = db.query("select * from posts where id = 1");
doSomethingWithPost(post)
doSomethingElse();

虽然这不会:

callback = function(post){
doSomethingWithPost(post)
}

db.query("select * from posts where id = 1",callback);
doSomethingElse();

好的,我知道我们应该使用回调。但是就事件堆栈而言,这为何起作用?Javascript是单线程的。在第一个示例行中,它使用了昂贵且阻塞的I /
O操作。第1行完成之前,第2行无法执行。这是因为第2行需要来自第1行的信息吗?还是因为I /
O事件从根本上阻止了操作,这意味着它们抓住了控制权,直到完成才将其交还给他人…

在第二个示例中,昂贵的I / O已移到一个函数中,现在我们有了一个回调函数。当然,只有在I /
O完成后才能执行回调。这不会改变。因此,一两个之间执行时间的差异主要必须是第二个请求到达服务器时将发生的情况。

如果第二个请求命中了示例1,则由于阻塞操作,它将无法处理直到请求1完成。但是在示例2中,将操作移动到函数中会自动产生子进程或充当多线程?如果Javscript是单线程的,除非采取某种并行处理方式,否则这仍然会带来问题。如果我们使用非阻塞技术(例如子进程等),那么函数/回调是否只能保证是非阻塞的。


问题答案:

想象您在面包店里操作收银机。您可以依次和同步地处理客户,如下所示:

  1. 点单
  2. 告诉贝克烤面包
  3. 等到烤面包
  4. 收费
  5. 送面包
  6. GOTO 1-下一个客户

那将非常慢。现在,试着依次接订单,但异步处理客户:

  1. 点单
  2. 告诉贝克烘烤面包,并在完成时通知您。收到通知时:
    1. 收费
    2. 送面包
  3. GOTO 1-下一个客户

更新: 我重构了上面,所以它更类似于回调。您(收银员)向面包师下达订单后将立即执行第3步。当面包师通知您面包准备好时,您将执行步骤2.1。

这样,您仍然可以提供尽可能多的面包-
您只能出售面包师可以烘烤的面包。但是,您可以以更有效的方式与客户打交道,因为您可以开始处理下一个客户,而不是闲着等待订单回来。

现在,您可以对此进行各种花哨的操作,并预先收取钱款,并告诉客户在桌子的另一端拿起面包,或类似的东西。我认为星巴克以这种方式相当“风骚”。收银员接订单,发出许多东西的要求,并告诉客户等到所有东西都放在提货区。超高效。

现在,假设您的朋友开始经营另一个收银机。他遵循您的异步示例。您可以更快地处理更多客户!请注意,您唯一要做的就是将您的朋友放到那里,并给他您的工作流程。

您和您的朋友是两个并行运行的单线程事件循环。这类似于两个接受请求的node.js进程。您不需要复杂的事情就可以并行化它,只需再运行一个事件循环即可。

因此,不,“将操作移入函数”不会“自动生成子进程”。它们更类似于警报-
完成警报后,请通知我,让我在这一点上接起来,“这一点”是您回调中的代码。但是回调仍将在相同的进程和相同的线程中执行。

现在,node.js还为IO运行内部线程池。这是从您这里抽象出来的:要继续进行面包店的类比,假设您有一个“面包店池”的面包店-
对您来说,站在收银机上,您不必了解这一点。您只需要给他们下订单(“一块酸面包”),并在收到通知后将其交付即可。但是,面包师们正在自己的“面包师池”中并行烘烤面包。



 类似资料:
  • 本文向大家介绍node.js回调函数之阻塞调用与非阻塞调用,包括了node.js回调函数之阻塞调用与非阻塞调用的使用技巧和注意事项,需要的朋友参考一下 首先,node.js作为javascript运行平台,它采用了事件驱动和异步编程的方式,通过事件注册和异步函数,开发人员可以提高资源利用率,服务器的性能也能得到改善。其次,对于前端人来说,node.js作为js的运行平台,我们可以通过编写系统级或者

  • 问题内容: 为什么可以用经node.js测试的JavaScript调用此函数: 为什么最后一次呼叫“” 有效?是node.js中的错误,V8引擎中的错误,正式未定义的行为还是对所有解释程序实际上有效的JavaScript? 问题答案: 似乎是Node REPL错误,将这两行放在会导致语法错误。 错误: 问题已提交#6634。 转载于v0.10.20。 v0.11.7已修复此问题。

  • 主要内容:阻塞代码实例,非阻塞代码实例Node.js 异步编程的直接体现就是回调。 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。 例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js

  • Node.js 异步编程的直接体现就是回调。 异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。 例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js

  • 问题内容: 最近,我开始使用Python3,它缺乏xrange的好处。 简单的例子: 1) Python2: 2) Python3: 结果分别是: 1) 1.53888392448 2) 3.215819835662842 这是为什么?我的意思是,为什么xrange被删除了?这是学习的好工具。对于初学者来说,就像我自己一样,就像我们都处在某个时刻。为什么要删除它?有人可以指出我正确的PEP,我找不

  • 问题内容: 对于以下代码段, 产生的输出是 为什么即使我尝试在fun()中修改a的值也没有修改? a和指针z的地址为何相同但值却不同? const_cast是否有某种未定义的行为? 问题答案: const_cast是否有某种未定义的行为? 是的 ,您的程序包含未定义的行为。 这意味着您不能对它的输出有任何期望。原因由C ++ 11标准的7.1.6.1/4给出: 除了可以声明任何声明的类成员(7.1