当前位置: 首页 > news >正文

一文简单入门Node.js

前言

JavaScript语言是网站开发必不可少的语言,只要有浏览器就能运行起来JavaScript代码。另外JavaScript还能单独运行在Node.js环境中,本文章重点介绍Node.js相关的基础内容,为深入了解Node.js铺路,后续会更新Node.js深入介绍。

Node.js安装及使用

安装很简单,在官网下载安装就行了,地址是 https://nodejs.org/zh-cn 。安装完后在控制台输入node -v 后能有显示则证明安装成功,这个时候可以开始各种倒腾了。

root@localhost:~$ node -v         
v16.17.0

可以创建一个JavaScript文件,用node命令来执行。

root@localhost:~$ echo 'console.log("hello world!")'> helloworld.js     
root@localhost:~$ node  helloworld.js
hello world!

Node.js源码初步分析

Node.js是怎么实现JavaScript代码执行的呢?Node.js源码地址是 https://github.com/nodejs/node/tree/main ,查看源码我们可以看到deps文件夹下面有很多依赖组件,其中最为核心的依赖组件是v8和uv文件夹。

├── deps
│   ├── acorn
│   ├── base64
│   ├── brotli
│   ├── cares
│   ├── cjs-module-lexer
│   ├── corepack
│   ├── googletest
│   ├── histogram
│   ├── icu-small
│   ├── llhttp
│   ├── nghttp2
│   ├── ngtcp2
│   ├── npm
│   ├── openssl
│   ├── undici
│   ├── uv
│   ├── uvwasi
│   ├── v8
│   └── zlib
组件名功能描述
v8V8 是 Google 发布的开源 JavaScript 引擎,采用 C++ 编写,在 Google 的 Chrome 浏览器中被使用。用于编译和执行JavaScript源代码,处理对象的内存分配,以及进行垃圾回收。
uvuv即为libuv,libuv 是一个多平台支持库,专注于异步 I/O,集成该组件能够更简单的实现异步I/O的服务端开发,同时该组件还为Node.js提供线程池,文件系统等功能。它本来就是为Node.js开发的,但它也被Luvit,Julia,uvloop和其他集成使用。
nghttp2nghttp2 是一个用 C 实现的 HTTP/2 库,支持 h2c,为其提供 HTTP/2 相关功能。
caresc-ares 是一个异步DNS解析器库。它为Node.js提供异步DNS并行查询功能。

Node.js基于v8 JavaScript 引擎和libuv实现了单线程/异步IO的JavaScript运行环境,显然没有线程资源抢夺场景,但是Node.js核心亮点不在于提供单线程JavaScript运行环境,而在于实现了跨平台的异步IO,其中linux系统下通过IO多路复用(epoll)+线程池来实现,Mac OS X系统下则是通过IO多路复用(kqueue)+线程池来实现,由于IO多路复用的实现依赖系统底层的实现,所以实现方法不一样。严格来说在linux和Mac OS X使用的都是同步IO,因为IO多路复用(select,poll,epoll等)就是同步IO,只是引入了线程池模拟实现了异步IO,让大家能够轻松使用异步语法(回调函数的处理),以下是官网提供的libuv实现异步IO的技术架构图。
在这里插入图片描述

由于JavaScript程序是单线程执行,代码肯定要有一定的执行顺序逻辑,定时器以及异步的回调函数何时执行也有讲究,Node.js提供了event_loop功能(事件循环机制)来判断什么时候执行。
比如下面的代码,输出的顺序是1,4,2,3。

console.log('1');
setTimeout(() => {
    console.log('2');
}, 1);
setTimeout(() => {
    console.log('3');
}, 1);
console.log('4');

比如下面的代码,输出的顺序是2,1。

setTimeout(() => {
  console.log(1);
}, 1);
/*模拟费时间的cpu计算,也可以用其他真实耗时的算法,比如计算素数和DFS全排列等*/
let now = new Date();
while(new Date () - now < 5*1000){}

从以上2个case可以总结出以下执行规则。
1.同步代码执行优先级都比setTimeout高。
2.setTimeout的定时不精准,会被其他同步代码影响。单线程定时器出现这个问题不出意外。
要了解更多的执行顺序的规则,就必须了解Node.js的事件循环机制。

Node.js事件循环机制

根据上面的case,可以大概得出Node.js的执行代码逻辑。
1.主线程执行同步代码。
2.主线程将异步任务插入到待执行任务队列中。
3.经过事件循环逻辑处理,按优先级执行队列里面的任务。
上面的逻辑应该比较容易理解,以下是官网提供的事件循环具体执行细节,包含了6个执行阶段。

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

阶段概述
定时器:本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。
待定回调:执行延迟到下一个循环迭代的 I/O 回调。
idle, prepare:仅系统内部使用。
轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。
检测:setImmediate() 回调函数在这里执行。
关闭的回调函数:一些关闭的回调函数,如:socket.on(‘close’, …)。
这些概述来自官网:https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/。

Node.js工程实践

Node.js版本管理

平时开发过程可能涉及不同的Node.js版本切换,可以通过安装nvm来进行管理,下载地址是https://github.com/nvm-sh/nvm ,下面是一些相关的命令例子。

root@localhost:~$ nvm use 16
Now using node v16.15.1 (npm v8.11.0)
root@localhost:~$ node -v
v16.15.1
root@localhost:~$ nvm install 12
Downloading and installing node v12.22.12...
Downloading https://nodejs.org/dist/v12.22.12/node-v12.22.12-darwin-x64.tar.gz...
########################################################################################################################### 100.0%
Computing checksum with shasum -a 256
Checksums matched!
Now using node v12.22.12 (npm v6.14.16)
root@localhost:~$ node -v
v12.22.12

Node.js 工程依赖包管理

Python工程可以通过pip工具来管理依赖包,JAVA工程可以通过maven工具来管理依赖包,自然Node.js也得有个依赖包管理工具。Node.js则是用npm来管理工程依赖包。
创建一个文件夹,然后cd进去执行npm init就是初始化Node.js工程,同时会在本地生成package.json文件。

mkdir app && cd app &&  npm init

package.json文件内容如下

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

可以通过npm install来安装其他的依赖包,如下安装koa(基于Node.js的web开发框架)。

npm install koa --save-dev

package.json文件更新如下

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "koa": "^2.13.4"
  }
}

No de => De no?

和Node一样提供JavaScript运行环境的还有一个叫Deno的程序,从名字上来看就是Node按No de的倒序,Deno是一个简单、现代和安全的 JavaScript、TypeScript 和 WebAssembly 运行时,它使用 V8 并在 Rust 中构建,具体可以查看官网安装和使用。
https://deno.land/

未完,持续更新。

相关文章:

  • 剑指offer专项 97-100笔记
  • Dubbo各种协议
  • 前端HTML5 +CSS3 2. HTML标签学习
  • 业务工人业务实体元模型-软件方法(下)第9章分析类图案例篇Part09
  • 乐观型人格分析,性格乐观的优缺点和职业发展分析
  • Dubbo之参数配置(一)
  • Dubbo之服务分组、分组聚合。
  • 15.ThreadLocal的作用
  • Android 11 adb无线调试使用方法
  • 【安卓学习之常见问题】自定义组件-刷新后跳到第一行
  • 为农田解渴为人民群众解忧 国稻种芯-桃源:湖南坚守抗旱一线
  • 【SSM框架】Mybatis详解11(源码自取)之表关联关系
  • docker安装ES(elasticsearch7.4.2)
  • C++—— pass by value and use std::move
  • STM32CubeIDE更新ST LINK驱动失败解决方法
  • 网络传输文件的问题
  • ES6语法详解(一)
  • fetch 从初识到应用
  • JavaScript中的对象个人分享
  • SpingCloudBus整合RabbitMQ
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 从0实现一个tiny react(三)生命周期
  • 工作中总结前端开发流程--vue项目
  • 后端_ThinkPHP5
  • 解析 Webpack中import、require、按需加载的执行过程
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 用Visual Studio开发以太坊智能合约
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • HanLP分词命名实体提取详解
  • scrapy中间件源码分析及常用中间件大全
  • zabbix3.2监控linux磁盘IO
  • 阿里云ACE认证学习知识点梳理
  • # 计算机视觉入门
  • #NOIP 2014# day.1 T2 联合权值
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (day6) 319. 灯泡开关
  • (Java数据结构)ArrayList
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (七)理解angular中的module和injector,即依赖注入
  • (三)终结任务
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (四)汇编语言——简单程序
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .describe() python_Python-Win32com-Excel
  • .NET MVC第三章、三种传值方式
  • .NET 常见的偏门问题
  • .net6使用Sejil可视化日志
  • .NET企业级应用架构设计系列之结尾篇
  • .pyc文件是什么?
  • @Autowired 与@Resource的区别