Node.js中的非阻塞或异步I/O是什么?

Ana*_*and 127 asynchronous nonblocking serverside-javascript node.js

在服务器端Javascript引擎的上下文中,什么是非阻塞I/O或异步I/O?我认为这被提到是优于Java服务器端实现的优势.

Jos*_*eph 303

同步与异步

同步执行通常是指按顺序执行的代码.异步执行是指执行不按代码中出现的顺序运行.在以下示例中,同步操作会使警报按顺序触发.在异步操作中,虽然alert(2)看起来执行第二个,但它没有.

同步:1,2,3

alert(1);
alert(2);
alert(3);
Run Code Online (Sandbox Code Playgroud)

异步:1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);
Run Code Online (Sandbox Code Playgroud)

阻止与非阻塞

阻止是指阻止进一步执行直到该操作完成的操作.非阻塞是指不阻止执行的代码.在给定的示例中,localStorage是一个阻塞操作,因为它会停止执行以进行读取.另一方面,fetch是非阻塞操作,因为它不会alert(3)因执行而停止.

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);
Run Code Online (Sandbox Code Playgroud)

好处

非阻塞异步操作的一个优点是可以最大限度地利用单个CPU和内存.

同步,阻塞示例

同步阻塞操作的一个示例是某些Web服务器(如Java或PHP中的Web服务器)处理IO或网络请求的方式.如果您的代码从文件或数据库中读取,则代码会"阻止"执行后的所有内容.在那段时间内,您的机器将保留内存和处理时间,以便执行任何操作的线程.

为了满足其他请求,而该线程已经停止取决于您的软件.大多数服务器软件所做的是产生更多线程来满足额外的请求.这需要更多的内存消耗和更多的处理.

异步,非阻塞示例

异步,非阻塞服务器(如在Node中制作的服务器)仅使用一个线程来为所有请求提供服务.这意味着Node的一个实例可以充分利用单个线程.创作者设计它的前提是I/O和网络操作是瓶颈.

当请求到达服务器时,它们一次只能被服务一个.但是,当服务的代码需要查询DB时,它会将回调发送到第二个队列,主线程将继续运行(它不会等待).现在,当DB操作完成并返回时,相应的回调从第二个队列中拉出,并在第三个队列中排队,在那里它们正在等待执行.当引擎有机会执行其他操作时(比如清空执行堆栈时),它会从第三个队列中获取回调并执行它.

  • 这是后者. (6认同)
  • 我不确定我理解你在PHP*中阻止*的第2段.你是说,"虽然PHP通常会阻止IO,但它并不是因为操作系统会自动对IO操作进行线程化."?或者,您是否说这不是PHP中的问题,因为PHP会自动为每个请求创建一个新线程,因此一个被阻止的请求不会停止整个PHP环境?(我猜后者......) (5认同)
  • @CharlieParker是的.异步操作与您的代码并行运行.但是,当主代码不忙时,"返回"异步操作结果的回调会在主代码中排队等待执行. (5认同)
  • 等等,如果是后者,那么非阻塞I / O PHP(例如reactPHP或其他东西)比阻塞I / O PHP有什么优势。仍然感到困惑 (2认同)
  • @CharlieParker [这是一篇文章](http://stackoverflow.com/q/15526546/575527),其中详细介绍了异步机制的内部。 (2认同)

Way*_*hiu 6

var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2
Run Code Online (Sandbox Code Playgroud)

代码示例