重学Node.js及其框架(Express, Koa, egg.js) 之 Nodejs基础(下)

本文涉及的产品
.cn 域名,1个 12个月
简介: 重学Node.js及其框架(Express, Koa, egg.js) 之 Nodejs基础

http状态码


HTTP状态码(HTTP Status Code),用以表示网页服务器超文本传输协议响应状态的3位数字代码。


http状态码的作用是服务器告诉客户端当前请求响应的状态,通过状态码就能判断和分析服务器的运行状态。


下面给出一些状态码的适用场景:


  • 100:客户端在发送POST数据给服务器前,征询服务器情况,看服务器是否处理POST的数据,如果不处理,客户端则不上传POST数据,如果处理,则POST上传数据。常用于POST大数据传输


  • 206:一般用来做断点续传,或者是视频文件等大文件的加载


  • 301:永久重定向会缓存。新域名替换旧域名,旧的域名不再使用时,用户访问旧域名时用301就重定向到新的域名


  • 302:临时重定向不会缓存,常用 于未登陆的用户访问用户中心重定向到登录页面


  • 304:协商缓存,告诉客户端有缓存,直接使用缓存中的数据,返回页面的只有头部信息,是没有内容部分


  • 400:参数有误,请求无法被服务器识别


  • 403:告诉客户端进制访问该站点或者资源,如在外网环境下,然后访问只有内网IP才能访问的时候则返回


  • 404:服务器找不到资源时,或者服务器拒绝请求又不想说明理由时


  • 503:服务器停机维护时,主动用503响应请求或 nginx 设置限速,超过限速,会返回503


  • 504:网关超时


分类


状态码第一位数字决定了不同的响应状态,有如下:


  • 1 表示消息


  • 2 表示成功


  • 3 表示重定向


  • 4 表示请求错误


  • 5 表示服务器错误


1xx


代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束


常见的有:


  • 100(客户端继续发送请求,这是临时响应):这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应


  • 101:服务器根据客户端的请求切换协议,主要用于websocket或http2升级


2xx


代表请求已成功被服务器接收、理解、并接受

常见的有:


  • 200(成功):请求已成功,请求所希望的响应头或数据体将随此响应返回


  • 201(已创建):请求成功并且服务器创建了新的资源


  • 202(已创建):服务器已经接收请求,但尚未处理


  • 203(非授权信息):服务器已成功处理请求,但返回的信息可能来自另一来源


  • 204(无内容):服务器成功处理请求,但没有返回任何内容


  • 205(重置内容):服务器成功处理请求,但没有返回任何内容


  • 206(部分内容):服务器成功处理了部分请求


3xx


表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向


常见的有:


  • 300(多种选择):针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择


  • 301(永久移动):请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置


  • 302(临时移动): 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求


  • 303(查看其他位置):请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码


  • 305 (使用代理): 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理


  • 307 (临时重定向): 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求


4xx


代表了客户端看起来可能发生了错误,妨碍了服务器的处理


常见的有:


  • 400(错误请求): 服务器不理解请求的语法


  • 401(未授权): 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。


  • 403(禁止): 服务器拒绝请求


  • 404(未找到): 服务器找不到请求的网页


  • 405(方法禁用): 禁用请求中指定的方法


  • 406(不接受): 无法使用请求的内容特性响应请求的网页


  • 407(需要代理授权): 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理


  • 408(请求超时): 服务器等候请求时发生超时


5xx


表示服务器无法完成明显有效的请求。这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生


常见的有:


  • 500(服务器内部错误):服务器遇到错误,无法完成请求


  • 501(尚未实施):服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码


  • 502(错误网关): 服务器作为网关或代理,从上游服务器收到无效响应


  • 503(服务不可用): 服务器目前无法使用(由于超载或停机维护)


  • 504(网关超时): 服务器作为网关或代理,但是没有及时从上游服务器收到请求


  • 505(HTTP 版本不受支持): 服务器不支持请求中所用的 HTTP 协议版本


事件循环


什么是事件循环?


事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁。

浏览器的事件循环是一个我们编写的JavaScript代码和浏览器API调用(setTimeout/AJAX/监听事件等)的一个桥梁,桥梁之间他们通过回调函数进行沟通。


Node的事件循环是一个我们编写的JavaScript代码和系统调用(file system、network等)之间的一个桥梁, 桥梁之间他们通过回调函数进行沟通的.


浏览器中的事件循环


主线程


宏任务队列:ajax、setTimeout、setInterval、DOM监听、UI Rendering等


微任务队列:Promise的then回调、 Mutation Observer API、queueMicrotask()等


队列中的回调函数,只有当满足条件的时候,他才会加入到队列中。


当主线程中的程序执行完毕后,就会去查看微任务队列中是否有事件,如果有则将它放在调用栈中。当微任务队列执行完毕,那么它将调用宏任务队列中的事件。在此期间,如果宏任务中的事件还会产生微任务,那么他将去执行微任务队列中的事件。


只要微任务队列中有事件,那么将不会执行宏任务队列中的事件。知道微任务队列中事件执行完毕。


Node.js中的事件循环


浏览器中的EventLoop是根据HTML5定义的规范来实现的,不同的浏览器可能会有不同的实现,而Node中是由libuv实现的。


libuv中主要维护了一个EventLoop和worker threads(线程池);


  • EventLoop负责调用系统的一些其他操作:文件的IO、Network、child-processes等 libuv是一个多平台的专注于异步IO的库,它最初是为Node开发的,但是现在也被使用到Luvit、Julia、pyuv等其他地方;


网络异常,图片无法展示
|


阻塞IO和非阻塞IO


操作系统为我们提供了阻塞式调用和非阻塞式调用:


  • 阻塞式调用: 调用结果返回之前,当前线程处于阻塞态(阻塞态CPU是不会分配时间片的),调用线程只有在得到调用结果之后才会继续执行。


  • 非阻塞式调用: 调用执行之后,当前线程不会停止执行,只需要过一段时间来检查一下有没有结果返回即可。


所以我们开发中的很多耗时操作,都可以基于这样的 非阻塞式调用:


  • 比如网络请求本身使用了Socket通信,而Socket本身提供了select模型,可以进行非阻塞方式的工作;


  • 比如文件读写的IO操作,我们可以使用操作系统提供的基于事件的回调机制; 非阻塞IO存在的问题:


但是非阻塞IO也会存在一定的问题:我们并没有获取到需要读取(我们以读取为例)的结果 那么就意味着为了可以知道是否读取到了完整的数据,我们需要频繁的去确定读取到的数据是否是完整的;这个过程我们称之为轮训操作;


libuv提供了一个线程池(Thread Pool),线程池会负责所有相关的操作,并且会通过轮训等方式等待结果;当获取到结果时,就可以将对应的回调放到事件循环(某一个事件队列)中;(这就好像浏览器中的时间回调,等到达一定条件,就会将事件放在相应的事件队列中) 事件循环就可以负责接管后续的回调工作,告知JavaScript应用程序执行对应的回调函数;


Node.js中事件循环阶段


  • 定时器(Timers):本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。


  • 待定回调(Pending Callback):对某些系统操作(如TCP错误类型)执行回调,比如TCP连接时接收到ECONNREFUSED。


  • idle, prepare:仅系统内部使用。


  • 轮询(Poll):检索新的 I/O 事件;执行与 I/O 相关的回调;


  • 检测:setImmediate() 回调函数在这里执行。


  • 关闭的回调函数:一些关闭的回调函数,如:socket.on('close', ...)。


Node.js中宏任务和微任务


从一次事件循环的Tick来说,Node的事件循环更复杂,它也分为微任务和宏任务:


  • 宏任务(macrotask):setTimeout、setInterval、IO事件、setImmediate、close事件;


  • 微任务(microtask):Promise的then回调、process.nextTick、queueMicrotask;


但是,Node中的事件循环不只是 微任务队列和 宏任务队列:


微任务队列:


  • next tick queue:process.nextTick;


  • other queue:Promise的then回调、queueMicrotask;


宏任务队列:


  • timer queue:setTimeout、setInterval;


  • poll queue:IO事件;


  • check queue:setImmediate;


  • close queue:close事件;


一道面试题


下面代码输出结果


setTimeout(() => {
      console.log("setTimeout")
    }, 0)
    setImmediate(() => {
      console.log("setImmediate")
    })
    // 上面代码谁先输出。
    都有可能,因为libuv库在处理事件循环的时候,每次处理的时间不同。并且会在IO操作停留很长时间,
    如果在这次处理时,setTimeout函数未加入到timers队列中,那么就是setImmediate先执行,
    反之setTimeout先执行。


相关文章
|
1月前
|
Web App开发 JavaScript 前端开发
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念,包括事件驱动、单线程模型和模块系统;探讨其安装配置、核心模块使用、实战应用如搭建 Web 服务器、文件操作及实时通信;分析项目结构与开发流程,讨论其优势与挑战,并通过案例展示 Node.js 在实际项目中的应用,旨在帮助开发者更好地掌握这一强大工具。
46 1
|
18天前
|
存储 JavaScript NoSQL
Node.js新作《循序渐进Node.js企业级开发实践》简介
《循序渐进Node.js企业级开发实践》由清华大学出版社出版,基于Node.js 22.3.0编写,包含26个实战案例和43个上机练习,旨在帮助读者从基础到进阶全面掌握Node.js技术,适用于初学者、进阶开发者及全栈工程师。
46 9
|
1月前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
1月前
|
JavaScript
使用node.js搭建一个express后端服务器
Express 是 Node.js 的一个库,用于搭建后端服务器。本文将指导你从零开始构建一个简易的 Express 服务器,包括项目初始化、代码编写、服务启动与项目结构优化。通过创建 handler 和 router 文件夹分离路由和处理逻辑,使项目更清晰易维护。最后,通过 Postman 测试确保服务正常运行。
51 1
|
1月前
|
JavaScript 前端开发 中间件
JS服务端技术—Node.js知识点
本文介绍了Node.js中的几个重要模块,包括NPM、Buffer、fs模块、path模块、express模块、http模块以及mysql模块。每部分不仅提供了基础概念,还推荐了相关博文供深入学习。特别强调了express模块的使用,包括响应相关函数、中间件、Router和请求体数据解析等内容。文章还讨论了静态资源无法访问的问题及其解决方案,并总结了一些通用设置。适合Node.js初学者参考学习。
44 1
|
1月前
|
JSON JavaScript 前端开发
使用JavaScript和Node.js构建简单的RESTful API
使用JavaScript和Node.js构建简单的RESTful API
|
1月前
|
Web App开发 JavaScript 前端开发
探索后端开发:Node.js与Express的完美结合
【10月更文挑战第33天】本文将带领读者深入了解Node.js和Express的强强联手,通过实际案例揭示它们如何简化后端开发流程,提升应用性能。我们将一起探索这两个技术的核心概念、优势以及它们如何共同作用于现代Web开发中。准备好,让我们一起开启这场技术之旅!
47 0
|
1月前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
1月前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的融合之道
【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
36 0
|
1月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
26 1
JavaScript中的原型 保姆级文章一文搞懂