开发者学堂课程【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”
);
//整段代码运行结果顺序是“0
00
”,“2
22
”,“1
11
”
,原因是因为writeFile是异步的,writeFile执行完后开启写入操作,不等文件写完后直接执行“222”,文件写完后又执行“111”。
//对于js代码,依然是单线程,当“222”打印完毕后,从队列里取出回调函数,再执行下一步事件,这样既实现了整个js单线程和异步非阻塞的IO操作。
执行结果:
console.log( '111");I
setTimeout(function () {
console.log( "222");
},
1000);
console.log( "333');
setTimeout(function()
{
console.log("444");
},
1000);
console.log( '555');
执行结果:
console.log( '111");I
setTimeout(function () {
console.log( "222");
},
0);
console.log( "333');
setTimeout(function()
{
console.log("444");
},
0);
console.log( '555');
执行结果:
console.log( '111');
setTimeout(function (
)
{
consoLe.log ( " 222");
},10);
console.log( '333');
setTimeout(function (
)
{
console.log( ' 444");
}
,0);
console.log( "555');
执行结果:
二、事件循环介绍及操作示例
事件循环:node.js 与浏览器端一样,内部基层都是 google’s v8 js 引擎。
浏览器 V8 引擎:
v8 里并不包含 windows 对象、ajax对象等。
v8 只包含堆和调用栈:
1. HEAP(MemoryAllocation):
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)方法
最后所有函数执行成功后从上往下递减
例子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函数
r
eturn foo();
//返回并调用foo函数
}
f
oo();
THE CALL STACK:
1.foo() //foo函数中继续调用foo函数
2.main() //进入入口函数
执行结果:
陷入循环,产生异常。
三、同步阻塞和异步回调示例操作及过程解释
同步—阻塞
同步--阻塞概念:一个事件执行完毕后,下一个事件才能开始执行。第一个事件如果没有执行完毕,第二个事件不可能开始执行。
例子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
.
g
etSynchronous(“/a”)
:
g
etSynchronous(“/
b
”)
g
etSynchronous(“/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" );
T
HE CONSOLE:
H
ello
H
i
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" );
C
ONSOLE:
1.H
ello
2
.Hi
3
.W
orld
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" );
C
ONSOLE:
1
.H
i
2
.W
elcome
S
TACK:
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 按钮左侧会将代码通过动画的方式演示出来。
如图所示: