JavaScript单线程模型如何处理耗时的任务?

时间:2014-11-15 02:39:45

标签: javascript node.js single-threaded

这个问题与JavaScript的sinlge线程模型有关。我知道javascript本质上是非阻塞的,因为它能够将回调添加到异步事件队列。但是如果回调函数确实需要很长时间才能完成,那么JavaScript是否会在那段时间内阻塞其他所有内容,因为它是单线程的? nodejs如何处理这样的问题?对于前端的开发人员来说,这是一个不可避免的问题吗?我问这个问题因为我已经读到了保持功能任务尽可能小的一般好习惯。这真的是因为javascript中的长任务实际上会阻止其他任务吗?

2 个答案:

答案 0 :(得分:0)

你的问题很大,所以我只关注一个部分。

  

如果回调函数确实需要很长时间才能完成,那么JavaScript是否会在那段时间内阻止其他所有内容,因为它是单线程的? (...)是否真的因为javascript中的长任务实际上会阻止其他任务?

非阻挡是一件美丽的事XD

最佳做法包括:

  • 将每个功能制作成最小功能形式。
  • 保持CallBacks异步,THIS是关于使用CallBacks的优秀帖子
  • 避免堆叠操作,(如嵌套循环)
  • 使用setTimeout()来制作可能阻止的代码
  • 还有很多其他的东西,Node.JS是无阻挡的黄金标准所以值得一看。

-

-

setTimeout()是无阻塞代码中最重要的函数之一

因此,假设你制作一个如下所示的时钟功能:

function setTime() {
    var date=new Date();
    time = date.getTime()
    document.getElementById('id').innerHTML = time;

}
while(true){setTime();}

它很成问题,因为这段代码很乐意循环自己,直到时间结束。没有其他功能会被调用。你想制动操作,以便其他东西可以运行。

function startTime() {
    var date=new Date();
    time = date.getTime()
    document.getElementById('id').innerHTML = time;
    setTimeout(startTime(),1000);
}

'的setTimeout();'制动循环并每1秒执行一次。无限循环是一个极端的例子。这一点是'setTimeout();'擅长将大型操作链制成小型操作链,使一切更易于管理。

答案 1 :(得分:0)

  

但是如果回调函数确实需要很长时间才能完成,那么JavaScript是否会在那段时间内阻止其他所有内容,因为它是单线程的?

  

nodejs如何处理这样的问题?

Node.js什么都不处理。如何处理并发取决于您和您的应用程序。现在,Node.js确实有一些工具可供您使用。您必须要了解的第一件事是Node.js基本上是V8(JavaScript引擎),其中轻量级库在JavaScript和本机代码之间进行了分割。虽然您的JavaScript代码本质上是单线程的,但本机代码可以并且确实创建了处理您工作的线程。

例如,当您要求Node.js从磁盘加载文件时,您的请求将传递给使用线程池的本机代码,并且您的数据将从磁盘加载。提出请求后,您的JavaScript代码将继续。这是Node.js上下文中“非阻塞”的含义。加载磁盘上的该文件后,本机代码会将其传递给Node.js JavaScript库,然后使用适当的参数执行回调。在后台工作正在进行时,您的代码继续运行,但是当您的回调处理该数据时,其他JavaScript代码确实被阻止运行。

这种架构使您可以获得多线程代码的大部分好处,而无需实际编写任何多线程代码,从而使您的应用程序保持简单。

  

我问这个问题因为我已经读到了保持功能任务尽可能小的一般好习惯。这真的是因为javascript中的长任务实际上会阻止其他任务吗?

我的理念始终是使用您需要的东西。确实,如果请求进入您的应用程序并且您对阻止的数据进行了大量JavaScript处理,则在此期间将不会处理其他请求。但请记住,如果您正在进行此类工作,那么无论如何您都可能受到CPU约束,并且将工作量增加一倍将导致两个请求都需要更长的时间。

实际上,大多数Web应用程序都是IO绑定的。它们从数据库中移植数据,重新格式化,然后通过网络发送出去。与应用程序只是等待从上游数据源收听的时间相比,它们处理数据的部分实际上并不是非常耗时。正是在这些应用程序中,Node.js才真正发光。

最后,请记住,您始终可以生成子进程以更好地分配负载。如果您的应用程序是一个罕见的应用程序,您在CPU绑定的JavaScript中执行99%的工作,并且您有一个包含许多CPU和/或内核的框,请将负载分成多个进程。