node.js 中单线程—非阻塞 IO 解释|学习笔记

简介: 快速学习 node.js 中单线程—非阻塞 IO 解释

开发者学堂课程【Node.js 入门与实战node.js 中单线程—非阻塞 IO 解释】学习笔记,与课程紧密联系,让用户快速学习知识

课程地址https://developer.aliyun.com/learning/course/588/detail/8250


node.js中单线程—非阻塞IO解释

  

目录

一、node.js中单线程的基本概念和操作示例

二、事件循环介绍及操作示例

三、同步阻塞和异步回调示例操作及过程解释

四、其他参考

 

一、node.js中单线程的基本概念和操作示例

解释下无论是 node.js 还是浏览器端,Java script 既是单线程,又是异步非阻塞IO模型

示例代码:

//执行文件操作

//------实现文件写入操作----------------

//1.加载文件操作模块,fs模块。

var fs = require( 'fs');

console.log("000”);

//2.实现文件写入操作

var msg ="Hello world,你好世界!';

//调用 fs.writeFile() 进行文件写入

//fs.writeFile(file, data[, options], callback)

fs.writeFile( ' ./hello.txt ' , msg,'utf8' , function (err){

console.log("111”);

//body . . .

//如果err === null,表示写入文件成功,没有错误!

//只要err里面不是 null,就表示写入文件失败了!

if (err) {

console.log('写文件出错啦!具体错误:' + err);

} else {

console.log( 'ok ');

}

}); //这部分代码是异步执行

console.log("222”);//整段代码运行结果顺序是“000”,“222”,“111,原因是因为writeFile是异步的,writeFile执行完后开启写入操作,不等文件写完后直接执行“222”,文件写完后又执行“111”。

//对于js代码,依然是单线程,当“222”打印完毕后,从队列里取出回调函数,再执行下一步事件,这样既实现了整个js单线程和异步非阻塞的IO操作。

执行结果:

image.png

console.log( '111");I

setTimeout(function () {

console.log( "222");

},1000);

console.log( "333');

setTimeout(function() {

console.log("444");

},1000);

console.log( '555');

执行结果:

image.png

console.log( '111");I

setTimeout(function () {

console.log( "222");

},0);

console.log( "333');

setTimeout(function() {

console.log("444");

},0);

console.log( '555');

执行结果:

image.png

console.log( '111');

setTimeout(function (){

consoLe.log ( " 222");

},10);

console.log( '333');

setTimeout(function () {

console.log( ' 444");

},0);

console.log( "555');

执行结果:

image.png

 

二、事件循环介绍及操作示例

事件循环:node.js 与浏览器端一样,内部基层都是 google’s v8 js 引擎。

浏览器 V8 引擎:

v8 里并不包含 windows 对象、ajax对象等。

v8 只包含堆和调用栈:

1. HEAP(MemoryAllocation):

image.png

2.STACK(The Call Stack):

(1) multiply(n, n)

(2)calcSquare(n)

(3)printSquare(n)

(4)main()

浏览器提供的js对象:

WEB APIs:

1.DOM(document)

2.ajax(XMLHTTPRequest)

3.setTimeout

调用的队列:

CALLBACK QUEUE:

1.onClick

2.onLoad

3.onDone

调用栈:

THE CALLSTACK

One thread == One call stack == One thing at a time

//一个调用栈等于一个单线程等于同一时间只执行一件事,js是单线程。

(1) multiply(n, n)

(2)calcSquare(n)

(3)printSquare(n)

(4)main()

js代码:

例子1:

function multiply (a, b) {

return a * b;   //定义两个数相乘返回相乘结果

}

function calcSquare (n)

{

return multiply(n, n);  //计算平方

function printsquare (n){   //打印平方

var result = calcsquare (n) ;console. log ( result);

}

printsquare ( 4);  

THE CALL STACK:

1. main():入口函数进入

2. printSquare(n):调用定义的函数

3. 执行calcSquare(n)方法

4. 执行multiply(n,n)方法

最后所有函数执行成功后从上往下递减

image.png

例子2:

function one ( ) {

throw new Error ( "oops ! " );

}

function two ( ) {

one() ;

)

function three ( ) {

two ( );

}

three ( ) ; 

THE CALL STACK

1.one()

2.two()

3.three(n)

4.main()

例子3:

fcuntion foo(){ //定义foo函数

return foo(); //返回并调用foo函数

}

foo();

THE CALL STACK:

1.foo()  //foo函数中继续调用foo函数

2.main()  //进入入口函数

执行结果:

image.png

陷入循环,产生异常。

 

三、同步阻塞和异步回调示例操作及过程解释

同步阻塞

同步--阻塞概念:一个事件执行完毕后,下一个事件才能开始执行。第一个事件如果没有执行完毕,第二个事件不可能开始执行。

例子1:

伪代码:无法进行执行

var a = $.getsynchronous ( " / a") ;  //同步请求服务器中a的地址,如果服务器无法返回a的地址,将无法执行下一步  

var b = $.getsynchronous ( "/b");

var c = $.getsynchronous ( " /c") ;

//  get data done, now log them out

console. log (a) ;

console.log (b) ;

console.log (c) ;  

//打印出a,b,c

THE CALL STACK:

1.main():进入入口函数

2.getSynchronous(“/a”)

getSynchronous(“/b”)

getSynchronous(“/c”)

//调用此函数,等待服务器响应,直到服务器返回结果,再执行下一步

3. console.log(a)

console.log(b)

console.log(c)

//执行完毕后,立刻打印a,b,c的结果,最终全部执行完毕

异步

异步回调

例子:

THE CODE:

console.log ("Hello" ) ;

setTimeont ( function () {

console.log ( "world" ) ;}, 5000);

console.log ("Hi" );

THE CONSOLE:

Hello

Hi

World

运作过程:

THE CALL STACK

1. main():进入入口函数

2. console.log(“Hello”):打印“Hello”。

3.setTimeout(callback):设置一个超时。

4.console.log(“Hi”):设置超时完成后,立刻执行打印。

5.console.log(“World”):回调函数进入,打印“World”。

并行&事件循环

例子:

CODE

console-log ( "Hello") ;

setTimeout ( function () {

console. log ( "world") ;

}, 5000);

console . log ("Hi" );

CONSOLE:

1.Hello

2.Hi

3.World 

STACK:

1. 首先进入入口函数

2. 执行第一段代码console.log(“Hello”)打印出”Hello

3. 开始执行setTimeout(callback)

4.继续执行console.log(“Hi”)打印出“Hi

5.callback:回调函数

6.回调函数将步骤调至console.log(“World”)打印“World”

WEB APIs:

1.setTimeout(callback)后台浏览器底层开启等待

EVENT LOOP:

CALL BACK

QUEUE

callback:”Hi”打印完毕后将setTimeout(callback)的回调函数放入队列中

例子2:

CODE:

console.log ( "Hi");

setTimeout (function () {

console. log ( "there");

}, 0) ;

console. log ( "welcome" );

CONSOLE:

1.Hi

2.Welcome

STACK:

1.进入入口函数main()

2.console.log(“Hi”)打印“Hi

3.立刻执行console.log(“Welcome”)打印“Welcome

4.callback继续执行。

WEB APIs:

1.”Hi打印完毕后setTimeout(callback)无需等待立刻放入队列中

EVENT LOOP:

CALLBACK

QUEUE

1. setTimeout(callback)无需等待立刻放入队列中

 

四、其他参考

其他参考:

在线动画演示:http://latentflip.com/loupe

参考视频:https://www.youtube.com/watch?v=8aGhZQkoFbQ

进入在线动画演示网站,将代码输入后,点击

Save + Run 按钮左侧会将代码通过动画的方式演示出来。

如图所示:

image.png

相关文章
|
6月前
|
Java Unix Linux
什么是阻塞IO和非阻塞IO
什么是阻塞IO和非阻塞IO
237 3
|
2月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
124 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
2月前
|
Java Linux
【网络】高并发场景处理:线程池和IO多路复用
【网络】高并发场景处理:线程池和IO多路复用
67 2
|
3月前
|
Prometheus 监控 Cloud Native
prometheus学习笔记之node-export
prometheus 监控 node-exporter
|
3月前
|
JSON 前端开发 JavaScript
socket.io即时通信前端配合Node案例
本文介绍了如何使用socket.io库在Node.js环境下实现一个简单的即时通信前端配合案例,包括了服务端和客户端的代码实现,以及如何通过socket.io进行事件的发送和监听来实现实时通信。
55 2
|
2月前
FFmpeg学习笔记(二):多线程rtsp推流和ffplay拉流操作,并储存为多路avi格式的视频
这篇博客主要介绍了如何使用FFmpeg进行多线程RTSP推流和ffplay拉流操作,以及如何将视频流保存为多路AVI格式的视频文件。
356 0
|
4月前
|
调度
多线程学习笔记
这篇文章是多线程学习笔记,涵盖了线程与进程的概念、多线程实现方式、线程状态、线程同步与不安全示例、死锁问题以及生产者与消费者问题等多线程编程的关键知识点。
多线程学习笔记
|
4月前
|
Java jenkins Shell
jenkins学习笔记之五:Maven、Ant、Gradl、Node构建工具集成
jenkins学习笔记之五:Maven、Ant、Gradl、Node构建工具集成
WXM
|
4月前
|
存储 缓存 算法
IO/线程的零拷贝
服务器在提供文件传输功能时,传统实现方式是通过读取磁盘文件内容,将其加载到用户空间的缓冲区,再通过网络 API 发送至客户端,这个过程涉及多次上下文切换和内存拷贝,导致性能下降。
WXM
64 12
|
4月前
|
JavaScript 前端开发 Ubuntu
如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
69 0