初识 nodejs

 

 

nodejs在2010年就活跃于各大网站,但是我在2015年才开始知道这个东西,因为当时公司是做媒体的,需要不停的采集一些数据同步到mongoDb中,就使用了nodejs写服务,但当时那还是别的大神写的代码,像我等小菜鸡根本无法企及。

那时才知道原来javascript还能做服务。之前的认识就停留在HTML中的脚本语言,比如,动态处理一些Dom元素,添加属性、修改样式、元素间组织等,最多发送一下get、post请求给后台服务,从没想过js也可以像java、C++等一样,可以作为服务端,处理请求、文件操作、数据库查询、异步操作等,并且请求处理速度还要优于传统的javaWeb。现在公司要求做一个restApi,这就又把nodejs拉回了我的视线。

概念:nodejs是依赖于Chrome的V8引擎的一套javascript运行环境。

既然是基于V8引擎的,那么我们先了解一下这个v8(https://v8.dev/docs),摘取了部分信息做了简单概括:谷歌的V8引擎是一个开源的高性能js引擎,使用C++编写,在谷歌浏览器、NodeJs等很多地方都有使用。它可以单独运行也可以嵌入到任意的C++程序中运行(这使得v8引擎和c++无缝融合)。 v8引擎可以执行js源代码,可以给对象分配内存,并且能像java一样垃圾回收(v8引擎的开发团队leader之前是开发jvm团队的核心成员)。

从GitHub(https://github.com/nodejs/node)上可以看到nodejs项目结构:

由此可见,宣称的nodejs实现的种种功能,实际上是c++做的底层,然后这个c++的项目又嵌入了v8引擎的源码,使得能在javascript平台上运行c++实现的功能,达到了借助c++强化javascript的目的。但是这并不是全部,nodejs宣称的“非阻塞”、“单线程”、“异步I/O”,高并发并没有体现,它得益于js本身的,基于事件驱动的特性(类似,onload、onclick、ondbclick、onmouseover...),并且针对此特性使用c++做了足够的优化(libuv等),于是就有了网上多如牛毛的nodejs高并发架构描述:

è¿éåå¾çæè¿°

  • Application:调用方,写js代码
  • V8:js代码一次性编译成机器码,并调用对应nodeAPI
  • Bindings:看作一个adaptor,例如Windows、Linux、Mac等不同系统都有自己的适配器,跨平台的核心内容
  • Libuv:任务执行库,单线程、高并发、异步IO的核心实现

回顾一下js:

单线程,(HTML5中新增了webWorker内容,允许在主线程执行期间插入耗时操作,但不会阻塞主线程的执行,不会干扰页面,且子线程受主线程控制,不得修改DOM元素,因此不违背js是单线程的),如果有需要事件驱动的,也就是需要回调的,主线程会顺序执行,将此类函数会加到event stack中,待主线程所有语句都执行完后才会去循环遍历event stack,取事件去执行。

setTimeout(function (){console.log(2);}, 1000);
setTimeout(function (){console.log(3);}, 1000);
console.log(1);
console.log(4);
// ================================
console.log(1);
console.log(4);
setTimeout(function (){console.log(2);}, 1000);
setTimeout(function (){console.log(3);}, 1000);

两种效果一样:
1
4
2
3

浏览器的事件循环机制(Event Loop),说白了也就是代码执行流程控制,实际上是通过一个执行栈和三个任务队列完成的,任务队列分为:global queue(全局队列);micro queue(微队列 / job); macro queue(宏队列 / task),执行优先级递减。global queue中存储的是立即执行的不需等待,不需回调,不需等事件触发的(实际上回调就是等待事件触发);micro queue中存储的一般是callback,比较常见的是Promise对象的then方法;macro queue中存储的是js本身的一些耗时操作,例如 setTimeout、setInterval、mutationObserve(H5)。先将global代码放入执行栈,执行完成后依次取micro队列执行,执行完成后执行macro队列的内容,如果macro队列中代码又引入了micro类型的方法,那么新的micro方法优先级依然高于macro方法,可以看出 macro 的优先级低于 micro,那么 UI rendering 之前我们可以做很多数据上的处理,比如 Vue 使用 mutationObserver 可以处理完所有数据处理后再统一做 UI render。

引用一个例子:

console.log(1);

setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
  
  Promise.resolve().then(() => {
    console.log(6)
  }).then(() => {
    console.log(7)
    
    setTimeout(() => {
      console.log(8)
    }, 0);
  });
})

setTimeout(() => {
  console.log(9);
})

console.log(10);

 

// 正确答案
// 注意:答案仅限于浏览器运行,如果使用nodejs运行练习代码结果会不同
1
4
10
5
6
7
2
3
9
8

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值