node基础知识
- http
- 常见漏洞
- linux
- ts
对Node.js的理解?
Node.js是一个基于Chrome V8引擎的服务端的js运行环境;是一个事件驱动、非阻塞式IO的模型;适用于实时应用程序,如即时通讯,I/O密集型应用,如写协作平台;不适用于CPU密集型应用,因为nodejs是单线程的。
Node.js提供了http、https模块、fs模块、path模块、event模块、stream模块、buffer模块、crypto 模块、os模块、child_proces 模块等核心模块。
http模块:用来创建HTTP服务器和客户端;
fs模块:nodejs的文件系统功能,用来读取和写入文件;
path模块:nodejs的路径功能,用来处理文件路径;
os模块:nodejs的操作系统功能,用于获取系统信息;
URL模块:用来解析URL,net模块:用来创建TCP服务器和客户端;
events 模块:用于实现事件驱动的编程,可以创建和处理事件;
child_process:子进程模块,用于创建和管理子进程;
buffer:缓冲区模块,用于处理二进制数据;
stream 模块:用于处理流式数据,可以读取和写入可流式的数据;
util 模块:包含一些实用工具函数,如继承、类型判断、错误处理等;
crypto 模块:加密模块提供加密和解密功能,包括哈希算法、对称加密和非对称加密等;
querystring 模块:用于解析和序列化 URL 查询字符串;
zlib
模块:提供压缩和解压缩功能,支持多种压缩算法;
nodejs的几个核心内置模块实现了事件、流、文件系统、网络通信。
Node.js事件驱动
观察者模式
Node.js提供了一个事件发射器类(EventEmitter),让开发者在自己的对像中发射事件,并监听这些事件,事件机制主要依赖于它的事件循环(Event Loop)和任务队列的设计,这种机制使得Node.js能够以非阻塞的方式处理I/O操作,从而提高程序的并发性和响应能力。
事件驱动工作流程为:引入events模块,创建eventEmitter对象->绑定事件处理程序(on函数绑定)->触发事件(emit触发)。
nodejs的事件循环
事件循环:事件循环(Event Loop)是Node.js处理异步I/O操作、定时器和事件等的机制。node使用chrome v8引擎作为js解释器,v8引擎分析代码后,主线程立即执行同步任务,而异步任务则由libuv引擎驱动执行,而且不同异步任务的回调事件会放在不同的队列中等待主线程执行,不再是简单的宏任务队列和微任务队列。因此在node.js中,虽然程序运行表现出的整体状态与浏览器中传统的js大致相同,先同步后异步,但是对于异步的部分,node则依靠libuv引擎来进行更复杂的管理。事件循环是一个无限循环,不断地从消息队列中取出消息并处理,队列中的消息主要包括I/O事件和回调函数。Node.js启动时会初始化事件循环,在每次循环中,Node.js会检查消息队列中是否有待处理的消息。如果有,就根据消息类型进行处理,若消息是一个I/O事件,Node.js就调用相应的回调函数来处理该事件,如果消息是一个回调函数,Node.js会立即执行该回调函数,事件循环在执行任务时的顺序是先同后异,先微后宏。
事件循环的六个阶段:
1.timers:计时器阶段,处理setTimeout()和setInterval()定时器的回调函数。
2.pending callbacks:待定回调阶段,挂起回调,用于处理系统级别的错误消息,如TCP错误或者DNS解析异常。
3.idle,prepare:闲置准备阶段,仅在内部使用。
4.poll:轮训阶段,等待I/O事件的发生,然后执行对应的回调函数,并且会处理定时器相关的回调函数,如果没有任何I/O事件发生,此阶段可能会使事件循环阻塞。
5.check:检查阶段,处理setImmediate()的回调函数。check的回调优先级比setTimeout高,比微任务要低。
6.close callbacks:关闭回调阶段,处理一些关闭的回调函数,比如socket.on("close")
宏任务和微任务:Node.js中宏任务包括setTimeout、setInterval等,微任务包括Promise的then、catch、finally以及process.nextTick等。
异步I/O操作:Node.js通过异步I/O操作实现了非阻塞I/O。当遇到I/O操作时,Node.js会立即返回一个结果给调用者,然后继续执行后续的代码。当I/O操作完成后,Node.js会将结果放入一个回调函数队列中,等待事件循环处理。
Node.js的全局变量:_filename:表示当前正在执行的脚本文件名;_direname:表示当前执行的脚本所在的目录。
nodejs的模块加载机制
Node.js 使用 CommonJS 模块系统,其中 require
函数用于加载模块。Node.js 会根据 require
提供的参数,在文件系统中搜索和解析模块。
Node.js 模块加载机制的特点:
缓存:已经加载的模块会被缓存,再次 require
时不会重新加载。
路径分析:根据 require
参数的形式,Node.js 会解析文件路径。相对路径会相对于 require
函数所在的文件。
标准模块:Node.js 内置了一些标准模块,如 http
,它们优先于 node_modules 文件夹中的模块。
第三方模块:如果没有找到标准模块,Node.js 会查找当前目录下的 node_modules
文件夹。
嵌套文件夹:如果上层目录中也有 node_modules
,Node.js 会向上遍历直到根目录。
模块后缀:Node.js 会尝试添加 .js
、.json
、.node
等后缀。
CommonJS和ES6模块的区别:
- 语法区别:ES6使用import和export关键字来导入和导出模块,CommanJS使用require和module.exports来导入和导出模块;
- 作用域区别:es模块的作用域是静态的,模块中定义的变量和函数不会污染全局作用域,CommonJS的作用域是动态的,模块中定义的函数和变量会被添加到全局作用域中;
- 异步加载:es模块可以异步加载,提高性能和减少启动时间,CommonJS只能同步加载;
- 导入方式:ES模块支持动态导入,在代码运行时使用到的模块才会被导入,CommonJS会在代码运行开始时候预先全部导入;
- 循环依赖:ES模块使用静态作用域,可以使用循环依赖。CommonJS kennel会因为循环依赖导致程序崩溃;
- 浏览器兼容性:ES在旧版本浏览器中无法使用,CommonJS在所有浏览器中可以使用。
ES模块更加现代灵活,支持动态导入,异步加载、静态作用域等特性,单CommonJS更加简单且适用于早期的no de.js环境。
promise的阶段
Node.js常用后端框架
express.js
express能够快速构建原型,提供简洁的接口,适用创建RESTful API,4.0以下版本不支持异步函数,中间件支持是他的一个重要特性,有大量可用的中间件。
Express框架的核心特点有哪些?
Express框架的核心特性包括中间件支持、路由功能、模板引擎支持、静态文件服务以及可扩展性。
高效路由:Express.js 提供了一种干净、简单的方法来管理各种 HTTP 请求并将它们分配给特定任务。
中间件支持:express允许支持处理HTTP请求,中间件是一个函数,可以访问请求对象、响应对象和应用程序的请求,响应周期中的下一个中间件函数。中间件可以用来处理各种任务,如日志记录、静态文件服务、路由等。
Koa.js
koa使用async/await语法以更同步的方式编写异步代码,适合处理复杂的业务逻辑,使用promise和async函数,消除了回调地狱,内置对错误处理的支持,可以通过context对req/res进行封装。
上下文对象(ctx):koa.js使用ctx来捕获请求和响应详细信息,该上下文被传递给每个中间件。
轻量级:koa是一个轻量级的框架,它本身只提供了一些基本的功能,其它功能可以通过中间件来扩展。
koa相对于express具有以下特点:
异步支持:koa支持异步编程,可以提高性能。
上下文:Koa引入了上下文的概念,它将请求和响应对象封装在一个对象中,使得代码更加简洁和易于理解。
错误处理:Koa提供了更好的错误处理机制,可以方便地处理和记录错误信息。
egg.js
egg注重简洁和易于维护,提供了大量的插件满足不同需求。egg由阿里巴巴开源,社区活跃度高,有很好的文档支持和解决问题的能力。
测试支持:egg.js提供了测试支持,可以方便地对应用进行单元测试和集成测试。
插件机制:Egg.js使用插件机制,可以将应用按照功能模块进行拆分,方便团队协作和项目维护。
RESTful API
什么是RESTful API ?它的主要特点是什么?
RESTful API是一种软件架构设计风格,它基于HTTP协议,提倡使用标准的HTTP方法(GET、POST、PUT、DELETE等)来实现资源的增删改查操作。
特点:基于资源,易于缓存,易于测试,易于扩展,支持多种数据格式、统一接口、无状态等。
缺点:因为无状态的概念,所以无法维持会话,
RESTful API设计原则
- 基于资源:将服务器上的数据视为资源,使用唯一的资源标识符(URI)来操作资源;
- 使用标准的HTTP方法:GET用来获取资源,POST用来创建资源,PUT用来更新资源,DELETE用来删除资源;
- 状态无关性:每个请求都包含足够的信息供服务器理解,服务器不会保存客户端的状态;
- 统一接口:接口设计要简单、统一,符合HTTP标准。
- 按需返回:返回的数据应当包含足够的信息,使得客户端能够理解如何使用。
在RESTful API中, URI的作用是什么?如何设计好的URI?
URI的作用是标识资源,URI通过其结构化的路径和参数,明确的指向了应用程序中的某个具体资源,每个URI都应代表一个特定的资源。
好的URI设计应该遵循以下原则:
- 协议:始终使用HTTP协议进行API与用户之间的通信,以确保数据传输的安全性。
- 域名:API应部署在专用域名下,若API简单且预计不会有大量的扩展,可以考虑放在主域名下;
- 版本:API的版本号应包含在URL中,也可以将版本号放在HTTP信息头中。
- 路径:在RESTful架构中,每个网址代表一种资源。网址中应避免使用动词,只使用名词,且名词通常与数据库中的表格名相对应。
- HTTP动词:对于资源的具体操作类型,由HTTP动词表示,如GET用于获取资源信息,POST用于创建新资源,PUT用于更新资源信息,DELETE用于删除资源。
REST API 中无状态的优缺点是什么?
优点:因为没有与会话相关的要求,并且可以在任何服务器上实现,所以无状态使API可以扩展到数百万并发用户,无状态通过消除任何服务端同步复杂性来简化REST API。
缺点:每个客户请求都必须附带大量补充数据,重复的数据传输可能会降低网络效率,无状态进一步降低了服务端对程序行为的控制。
什么是HATEOAS(超媒体即应用状态引擎)?为什么它在RESTful API中很重要?
在API响应中包含超媒体链接,使客户端能够通过这些链接动态地发现和访问相关资源。提升了RESTful API的可发现性和响应的自解释性,同时也减少了客户端与服务器之间的耦合度,提高了API的可扩展性和适应性。
在RESTful API如何处理缓存和性能优化?
使用HTTP缓存头:设置合适的头知道客户端和中间缓存如何缓存响应;
使用查询参数分页:对大数据集使用分页,并提供查询参数来控制返回结果的数量和偏移;
请求合并:客户端可以合并多个API请求到单个请求中,减少HTTP连接数;
使用CDN:部署CDN来缓存静态内容和API响应;
异步处理和队列:对于耗时的操作,可以使用异步处理和消息队列来避免阻塞请求;
服务端的缓存:使用内存缓存来存储经常被请求的数据;
性能监控和分析:使用工具监控API的性能指标,分析瓶颈,进行性能优化。