我在想它,这就是我提出的:
假设我们有这样的代码:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
Run Code Online (Sandbox Code Playgroud)
请求进来,JS引擎开始逐步执行上面的代码.前两个呼叫是同步呼叫.但是当谈到setTimeout方法时,它就变成了异步执行.但是JS立即从它返回并继续执行,这被称为Non-Blocking或Async.并继续致力于其他等
执行结果如下:
ACDB
所以基本上第二个setTimeout完成第一个,它的回调函数比第一个更早执行,这是有道理的.
我们在这里谈论单线程应用程序.JS引擎继续执行此操作,除非它完成第一个请求,否则它不会进入第二个请求.但好处是它不会等待阻塞操作,比如setTimeout解决所以它会更快,因为它接受新的传入请求.
但我的问题出现在以下几个方面:
#1:如果我们讨论的是单线程应用程序,那么setTimeouts当JS引擎接受更多请求并执行它们时,什么机制会处理?单个线程如何继续处理其他请求?什么工作,setTimeout而其他请求继续进入并执行.
#2:如果这些setTimeout函数在幕后执行,而有更多请求进入和执行,那么在幕后执行异步执行的是什么?我们谈到的这件事叫EventLoop什么?
#3:但是不应该将整个方法放入,EventLoop以便整个事件被执行并调用回调方法?这是我在谈论回调函数时所理解的:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,JS引擎如何知道它是否是异步函数,以便它可以将回调EventLoop? Perhaps something like the放在C#中的async`关键字中,或者某种属性指示JS引擎将采用的方法是异步方法并应相应地对待.
#4:但是一篇文章说的与我猜测事情可能如何起作用完全相反:
Event Loop是一个回调函数队列.执行异步函数时,回调函数将被推入队列.在执行异步函数之后的代码之前,JavaScript引擎不会开始处理事件循环.
#5:这里有这个图像可能会有所帮助,但图像中的第一个解释是说第4个问题中提到的完全相同:

所以我的问题是要对上面列出的项目做一些澄清?
语法的哪一部分提供了此函数应该在其他线程中运行并且是非阻塞的信息?
让我们考虑node.js中的简单异步I/O.
var fs = require('fs');
var path = process.argv[2];
fs.readFile(path, 'utf8', function(err,data) {
var lines = data.split('\n');
console.log(lines.length-1);
});
Run Code Online (Sandbox Code Playgroud)
究竟是什么让它在背景中发生?任何人都可以准确地解释它或粘贴一些好资源的链接?我看到的每个地方都有关于回调是什么的大量信息,但没有人解释为什么它实际上是这样的.
这不是关于node.js的具体问题,而是关于每种编程语言中回调的一般概念.
编辑:
可能我提供的例子并不是最好的.所以我们不要考虑这个node.js代码片段.我一般都在问 - 当遇到回调函数时,程序是如何继续执行的.什么是语法使回调概念成为非阻塞概念?
提前致谢!
我已经阅读了很多关于NodeJ如何工作的文章.但我仍然无法弄清楚Nodej的内部线程是如何进行IO操作的.
在这个答案/sf/answers/1424258181/中,他说NodeJ的线程池中有4个内部线程来处理I/O操作.那么,如果我同时有1000个请求,每个请求都想进行I/O操作,例如从数据库中检索大量数据.NodeJs将分别将这些请求传递给这4个工作线程,而不会阻塞主线程.因此,NodeJ可以同时处理的最大I/O操作数是4个操作.我错了吗?.
如果我是对的,剩下的请求将在哪里处理?主要的单线程是非阻塞的并且继续将请求驱动到相应的操作员,那么这些请求在所有工作线程充满任务的情况下会在哪里进行?.
在下图中,所有内部工作线程都充满了任务,假设它们都需要从数据库中检索大量数据,并且主要单线程继续向这些工作者发送新请求,这些请求将在何处进行?是否有内部任务queuse来存储这些请求?

我正在通过节点文档进行事件循环,我感到非常困惑.它说 -
timers: this phase executes callbacks scheduled by setTimeout() and
setInterval().
I/O callbacks: executes almost all callbacks with the exception of close callbacks, the ones scheduled by timers, and setImmediate().
idle, prepare: only used internally.
poll: retrieve new I/O events; node will block here when appropriate.
check: setImmediate() callbacks are invoked here.
close callbacks: e.g. socket.on('close', ...).
Run Code Online (Sandbox Code Playgroud)
然后在详细的轮询阶段,他们说它执行使用计时器调度的计时器,并且还处理轮询队列中的i/o事件.我的困惑是,我们已经有那些回调的计时器阶段和i/o回调阶段,然后轮询阶段完成的工作是什么.它还说线程可能在轮询阶段睡觉,但我没有正确.
我的问题是 -
在这一点上我很困惑.任何帮助将不胜感激.
我对Node js的架构和性能有疑问.
我已经完成了一些关于这个主题的阅读(包括Stack Overflow),我还有几个问题.我想做两件事:
Node具有单线程,异步事件处理架构
单线程 - 有一个事件线程可以调度异步工作(结果通常是I/O但可以是计算)并执行回调执行(即处理异步工作结果).
事件线程在无限的"事件循环"中运行,执行上述2个作业; a)通过调度异步工作来处理请求,以及b)注意先前的异步工作结果已准备好并执行回调以处理结果.
这里的常见类比是餐厅订单接收者:活动线程是一个超级快速的服务员,从餐厅接受订单(服务请求)并将订单发送到厨房准备(发送异步工作),但也注意到当食物准备就绪(异步结果)并将其送回表格(回调执行).
服务员不做任何食物; 他的工作是尽快从餐厅到厨房来回走动.如果他陷入餐厅的订单陷入困境,或者如果他被迫回到厨房准备其中一餐,系统就变得效率低下并且系统吞吐量受损.
异步 由请求(例如Web请求)产生的异步工作流在逻辑上是一个链:例如
FIRST [ASYNC: read a file, figure out what to get from the database] THEN
[ASYNC: query the database] THEN
[format and return the result].
Run Code Online (Sandbox Code Playgroud)
上面标有"ASYNC"的作品是"厨房工作","FIRST []"和"THEN []"代表服务员开始回调的参与.
像这样的链以3种常见方式以编程方式表示:
嵌套函数/回调
用.then()链接的承诺
async()异步结果的异步方法.
所有这些编码方法都非常相同,尽管asynch/await似乎是最干净的,并且使得异步编码的推理更容易.
问题
我的问题涉及使用OS支持的异步操作,实际执行异步工作的人,以及这种体系结构比"按每个请求生成一个线程"(即多个cooks)体系结构更高效的方式:
通过使用跨平台异步库libuv设计节点库是异步的,对吗?这里的想法是libuv为节点(在所有平台上)提供一致的异步I/O接口,但随后使用平台相关的异步I/O操作吗?在I/O请求"一直向下"到OS支持的异步操作的情况下,谁正在"做工作"等待I/O返回并触发节点?它是内核,使用内核线程吗?如果不是,谁?无论如何,这个实体可以处理多少个请求?
我已经读过libuv也在内部使用了一个线程池(通常是pthreads,每个核心一个?).这是为了"包装"不像"async"那样"完全向下"的操作,这样一个线程就可以用来等待同步操作了,所以libuv可以提供一个异步API吗?
关于性能,用于解释类似节点的体系结构可以提供的性能提升的通常说明是:画出(可能更慢和更胖)线程每请求方法 - 产生的延迟,CPU和内存开销一堆线程只是坐在等待I/O完成(即使他们没有忙碌等待)然后将它们拆除,节点很大程度上让它消失了,因为它使用了一个长期存在的事件线程来将异步I/O发送到OS /内核,对吗?但是在一天结束的时候,SOMETHING正在睡眠互联网并在I/O准备就绪时被唤醒...是否认为内核比用户线程更有效?最后,请问由libuv的线程池处理的情况怎么样...这似乎与每个请求线程的方法类似,除了使用池的效率(避免启动和拆除),但是在这种情况下,当有很多请求并且池有积压时会发生什么?...延迟增加,现在你做的比每个请求的线程更糟,对吧?
Node.js服务器适用于支持回调函数的基于事件的模型.但我无法理解它比线程等待系统IO的传统线程服务器更好.在基于线程的模型的情况下,当线程需要等待IO时,它被抢占,因此不消耗CPU周期因此不会导致等待时间.
Node.js如何改善等待时间?
我正在努力理解异步性的概念。以下关于异步操作的描述大致正确吗?
\n如果一段代码需要很长时间才能完成,则可能会出现问题。这是因为 i) 它会阻止下面的代码运行,并且在后台加载硬代码时运行它可能会很好。ii) 事实上,JS 可能会在硬代码\xe2\x80\x99s 完成之前尝试执行下面的代码。如果下面的代码依赖于硬代码,那么 \xe2\x80\x99 就会出现问题。
\n一个解决方案是:如果一个操作需要很长时间才能完成,您希望在处理原始线程的同时在单独的线程中处理它。只需确保主线程不引用异步操作返回的内容即可。JS 使用事件队列来解决这个问题。异步操作在主线程之后执行的事件队列中执行。
\n但即使是事件队列也可能遇到与主线程相同的问题。如果位于 fetch2 之上的 fetch1 需要很长时间才能返回 Promise,而 fetch2 则不会\xe2\x80\x99t,则 JS 可能会在执行 fetch1 之前开始执行 fetch2。这是Promise.all很有用的地方,因为在 fetch1 和 fetch2\xe2\x80\x99s 承诺都得到解决之前,它不会继续执行异步操作中的下一步。
另请注意, I\xe2\x80\x99ve read when chaining .then,这算作一个异步操作,因此我们始终可以保证后续操作.then仅在.then之前执行|解决其承诺时才会执行。
我试图找出一个有效的算法来改变一堆节点上的很多类,我发现我对javascript如何遍历DOM有一个很大的漏洞.
浏览器/ javascript是否使用像闪存一样的弹性赛道?或者它是更多的事件驱动,每次有变化时重绘整个显示?
"弹性跑道"是一个闪光范例,你可以想象一个闪光环绕的大环.在用户处理期间,时间变化积累,并且在闪存处理期间,闪存引擎会四处奔跑并一遍又一遍地应用所有更改.
替代方案是一个事件模型,每次属性更改时,整个屏幕都会重新绘制 - 这可能是浏览器所做的,但我不确定.
我可以想到混合算法,如果没有任何变化,没有任何事情发生 - 但如果有它们被允许建立 - 有点像我的水槽上的菜.
有没有人能够快速描述用于处理属性更改和DOM插入的算法.
我正在开发NodeJS应用程序。有一个特定的RESTful API(GET),当用户触发该API时,它要求服务器执行大约10到20个网络操作才能从不同来源获取信息。所有这些网络操作都是异步回调,一旦它们全部完成,结果将由nodejs应用程序合并并发送回客户端。所有这些操作都是通过async.map函数并行启动的。
我只想了解一下,因为nodejs是单线程的,并且不使用多核计算机(至少不是没有集群),所以当节点有许多回调要处理时,节点如何扩展?回调的实际处理是取决于节点的单线程是否空闲,还是与主线程并行处理回调?
我问的原因是,我看到我的20个回调的性能从第一个回调降到了最后一个。例如,第一个网络操作(从10到20)需要141毫秒才能完成,而最后一个网络操作则需要约4秒钟(以从执行该功能到函数的回调返回值或一个错误)。它们都是相同的网络操作,因此命中相同的数据源,因此数据源不是瓶颈。我知道一个事实,即数据源响应单个请求所花费的时间不超过200ms。
我找到了这个线程,所以在我看来,一个线程需要处理所有回调和即将出现的新请求。
所以我的问题是,对于将触发许多回调的操作,优化其性能的最佳实践是什么?
javascript ×9
node.js ×7
asynchronous ×3
event-loop ×3
callback ×2
algorithm ×1
async-await ×1
dom ×1
performance ×1