node.js基础学习

2023-11-15

什么是node?

简单来说,node是JS的一种运行环境。在此之前,我们都知道JS可以在浏览器中运行,可以为网页添加各种交互,因此,浏览器也是JS的运行环境。随着Chrome浏览器的发布,带来了全新的V8引擎。经过多年的发展和优化,性能和安全性都已经达到了相当的高度。而 Node.js 则进一步将 V8 引擎加工成可以在任何操作系统中运行 JavaScript 的平台。
在这里插入图片描述
两个运行环境如图所示,他们都包含了JavaScript语言标准ECMAScript,在浏览器环境还有

  • 浏览器对象模型(Browser Object Model,简称 BOM),也就是 window 对象
  • 文档对象模型(Document Object Model,简称 DOM),也就是 document 对象

在node中也有特有的代表不同含义的对象

  • global:和window一样,任何global对象上的属性都可以被全局访问到。
  • process:所有全局执行上下文中的内容都在process对象中,提供了与操作系统的简单接口。
  • buffer:让 JavaScript 也能够轻松地处理二进制数据流,结合 Node 的流接口(Stream),能够实现高效的二进制文件处理。
  • __filename:当前所运行 Node 脚本的文件路径。
  • __dirname:当前所运行 Node 脚本所在目录路径。

模块系统

node中的每一个文件都是一个模块,有着自己的作用域。使用Commonjs模块规范,该模块系统有三个核心的全局对象:require、module和exports。

  • require

require 用于导入其他 Node 模块,其参数接受一个字符串代表模块的名称或路径,通常被称为模块标识符。

绝对模块:node通过在其内部node_modules查到的模块,或者node内置的例如fs这样的模块,可以直接通过名字来requirevar fs = require('fs')

相对模块将require指向一个相对工作目录中的JavaScript文件,比如我们在同一目录中创建名为module_a.js、module_b.js、main.js三个文件,如果我们想要在main.js中引入module_a.js和module_b.js,则需要写作require('./module_a')

  • exports
    exports用于导出当前node模块的内容,例如有一个module_a.js文件
function a {
	console.log('module_a.js')
	}
//导出函数a
exports.a = a

通过将a函数添加到exports对象中,其他模块就可以通过require引入调用。

  • module
    Node内部有个Module的构造函数,每个文件中的module都是其的一个实例。我们在node文件中可以通过console.log(module)来查看其包含的属性,export其实就是对module.exports的引用

单线程

举个例子:假设一个用户分别向node服务器和PHP服务器各同时发起两次请求

//node
var books =['node','php'];
function serveBooks(){
	var html = '<b>' + books.join('</b><br><b>') + '<b>';
	books = [];
	return html;
}
//php
$books = array('node','php');
function serveBooks(){
	$html = '<b>' . books.join('</b><br><b>') . '<b>';
	$books = array()
	return $html;
}

在上述的两个serveBooks函数中,都将books数组重置了。

  • node会将完整的book返回给第一次请求,而第二次则返回一个空的book.
  • PHP两次请求都能返回完整的book

这两者的区别就在于基础架构上。node采用了一个长期运行的线程(单线程),使得第二次请求的book是第一次请求操作过的。而Apache会产生多个线程,每次都会刷新状态,因此不会受到影响。

node为JavaScript引入了一个复杂的概念:共享状态的并发。通俗的说,在node中,要谨慎处理回调函数对当前内存中变量的修改,并且还要注意对错误的处理是否会潜在地修改这些状态。这可能会导致整个进程不可用。

非阻塞IO

既然node执行时只有一个线程,那又是如何做到高并发的,这就要说到node的另一个特点,非阻塞(异步)

//php
print('Hello');
sleep(5);
print('World');
//node
console.log('Hello')
setTimeout(function(){
	console.log('stop')
},3000)
console.log('World')

观察上面的两段代码有什么区别
除了语义上的区别(Node.js使用了回调函数)以外,两者最大的区别体现在了阻塞和非阻塞上,在PHP中,sleep()阻塞了线程的执行,导致World无法输出,而node使用了事件轮询,因此这里的setTimeout是非阻塞的(异步),也就是说在3S之后会正常输出World。

事件轮询:从本质上来说Node会先注册事件,然后不停的询问内核这些事件是否已经分发。当事件分发时,对应的回调函数就会执行。如果没有事件触发,则会继续执行其他代码。

V8引擎执行JavaScript的速度非常快,结合非阻塞IO确保了单线程执行时,不会有因为数据库访问或者是硬盘访问等操作导致操作会被挂起。

事件循环

node中的事件循环分为三个队列,事件循环会按顺序执行三个队列中的事件。

  1. timer:setTimeout、setInterval 定时器操作
  2. poll:文件读写、网络请求、数据库操作等I\O操作
  3. check:setImmediate

如果timer队列和check队列都为空的时候,循环会在poll队列等待(优先处理IO事件)。
timer事件在node中的最小间隔为1ms,因此与setImmediate事件的执行顺序不确定。我们希望是确定的,当存在这种情况时,会将其同时放在一个IO事件的回调中,这样事件循环就从poll阶段开始,总是会先执行setImmediate了

process.nextTick() 属于微任务,并且总是最先执行.


事件模块

在这里插入图片描述

fs模块

fs模块是唯一一个同时提供同步和异步的API模块,用于对系统文件及目录进行读写操作。

  • fs.readFile(filename,[option],callback) 方法读取文件。
  • fs.writeFile(filename,data,[options],callback)写入内容到文件。
    fs.readfs.write功能类似fs.readFilefs.writeFile,但提供更底层的操作,需要使用fs.open打开文件和fs.close关闭文件。实际应用中多用fs.readFilefs.writeFile
  • fs.open(path,flags,[mode],callback)方法用于打开文件,以便fs.read()读取。
  • fs.read(fd,buffer,offset,length,position,callback)接收6个参数。用于关闭文件
//异步写法
var fs = require('fs');

fs.readdir(__dirname, function(err, files) {
    console.log(files);
});
//同步写法
var fs = require('fs');
console.log(fs.readdirSync(__dirname))

TCP

传输控制协议(TCP)是一个面向连接的协议,它保证了两台计算机之间数据传输的可靠性和顺序。

  • 面向连接:当在TCP连接内进行数据传递时,发送的IP数据报包含了标识该连接以及数据流顺序的信息。
  • 面向字节:TCP对字符以及字符编码是不关心的,对消息格式没有严格的约束,具有很好的灵活性。
  • 可靠性:当数据发送之后,发送方在窗口时间内等待“消息送达”的确认消息,否则会重发消息。可以有效解决网络错误或者网络阻塞的情况。
  • 流控制:所谓流控制就是让发送发送速率不要过快,让接收方来得及接收。原理这就是运用TCP报文段中的窗口大小字段来控制,发送方的发送窗口不可以大于接收方发回的窗口大小。
  • 拥堵控制:TCP会通过控制数据包的传输速率来避免拥堵的情况。
var net = require('net');
var tcp_server = net.createServer();  // 创建 tcp server

var Sockets = {};
var SocketID = 1;

// 监听 端口
tcp_server.listen(5678,function (){
    console.log('tcp_server listening 5678');
});

// 处理客户端连接
tcp_server.on('connection',function (socket){
    console.log(socket.address());
    Sockets[SocketID] =socket;
    SocketID++;
    DealConnect(socket)
})

tcp_server.on('error', function (){
    console.log('tcp_server error!');
})

tcp_server.on('close', function () {
    console.log('tcp_server close!');
})


// 处理每个客户端消息
function DealConnect(socket){

    socket.on('data',function(data){
        data = data.toString();
        // 向所有客户端广播消息
       for(var i in Sockets){
           Sockets[i].write(data);
       }
        // socket.write(data);
        console.log('received data %s',data);
    })

    // 客户端正常断开时执行
    socket.on('close', function () {
        console.log('client disconneted!');
    })
// 客户端正异断开时执行
    socket.on("error", function (err) {
        console.log('client error disconneted!');
    });
}

HTTP

超文本传输协议(HTTP)是属于TCP的上层协议,构建在请求和相应的概念之上。nodejs中的http模块中封装了一个HTPP服务器和一个简易的HTTP客户端,http.Server是一个基于事件的http服务器,http.request则是一个http客户端工具,用于向http服务器发起请求。而上面的createServer方法中的参数函数中的两个参数req和res则是分别代表了请求对象和响应对象。其中req是http.ServerRequest的实例,res是http.ServerResponse的实例,这可以从nodejs中的源码中获取这个信息

//一个简单的http服务器
var http=require("http");

http.createServer(function(req,res){
    res.writeHead(200,{
        "content-type":"text/plain"
    });
    res.write("hello World");
    res.end();
}).listen(3000);

打开浏览器,输入localhost:3000,如果看到屏幕上的hello World了,这表明这个最简单的nodejs服务器已经搭建成功了。

Connect

  • Node.js为常规的网络应用提供了基本的API。然而,实际情况下,绝大部分网络应用都需要完成一系列类似的操作,这些类似的操作你一定不想每次都重复地基于原始的API去实现。
  • Connect是一个基于HTTP服务器的工具集,它提供了一种新的组织代码的方式来与请求、响应对象进行交互,称为中间件(middleware)。
  • 中间件具有代码复用的好处。在没有使用中间件的情况下,处理请求的这些代码都放在一个简单的事件处理器中(createServer的回调函数中),这将会是一个非常复杂的处理过程。而使用中间件后会将应用拆分为更小单元(让代码有更强大的表达能力),还能够实现很好的重用性。
var http = require('http'),
    fs = require('fs');

/**
 * 创建服务器
 */
var server = http.createServer(function(req, res) {
    // 检查URL是否和服务器目录下的文件匹配,如果匹配,则读取该文件并展示出来
    // 请求.jpg图片
    if('GET' == req.method 
        && '/images' == req.url.substr(0, 7) 
        && '.jpg' == req.url.substr(-4)) {
        // 返回对应图片
        // ...
        fs.stat(__dirname + req.url, function(err, stat) {
            // 如果检查文件是否存在时发生错误,则终止进程并发送HTTP 404状态码告知无法找到请求的图片。
            // 对于stat成功但是路径所表示的并非是文件时,也要做此处理。
            if(err || !stat.isFile()) {
                res.writeHead(404);
                res.end('Not Found');
                return;
            }

            // 发送图片资源
            serve(__dirname + req.url, 'application/jpg');
        });

    } else if('GET' == req.method && '/' == req.url) {
        // 发送html文件,默认请求index.html
        // ...
        // console.log(__dirname);
        serve(__dirname + '/index.html', 'text/html');
    } else {
        // 处理其他请求,返回404错误码
        res.writeHead(404);
        res.end('Not found');
    }


    /**
     * 根据文件路径来获取文件内容,并添加'Content-Type'头信息
     * @param  {[type]} path 文件路径
     * @param  {[type]} type Content-Type头信息
     * @return {[type]}      [description]
     */
    function serve(path, type) {
        res.writeHead(200, {'Content-Type': type});
        fs.createReadStream(path).pipe(res);
    }
});

server.listen(3000);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

node.js基础学习 的相关文章

  • exec 'node app' 挂在 gulp 任务中

    这个 gulp 任务挂起exec node config app 线 第一的exec工作正常 但第二个挂起 gulp task test function cb var exec require child process exec exe
  • 使用 React js 和 Express API 服务器通过 fetch 发布对象

    我在 fetch 中的 post 方法遇到麻烦 因为我的服务器从客户端接收到一个空对象 我已经检查了客户端 但无法发送我想要发送的值 这是我的服务器 const express require express const app expre
  • 为什么 Node.js 0.12.0 版本中的 V8 需要 SSE2 CPU 指令?

    尝试将 Node js 从 0 10 x 升级到 0 12 0 首先注意到的是 我收到一条错误消息 指出我的 CPU 不支持 SSE2 指令 实际上并不支持 尝试从源代码编译 Node js 但由于同样的原因失败了 在deps v8 src
  • Express 是否从隐藏(点)文件夹提供静态文件

    我的应用程序正在提供这样的静态文件夹 app use static serveStatic dirname view my static folder 如何配置服务器来提供隐藏文件夹服务 所以如果我有 view my static fold
  • 如何在 NextJS 中记录所有路由

    我对 NextJS 非常陌生 我目前有一个非常简单的应用程序 它提供少量页面 如果路由不存在 则返回 404 页面 我想记录每个请求 包括不存在的页面并返回 404 页面 我正在 docker 容器内运行该应用程序 或者我希望将日志写入标准
  • 如何在浏览器中实现HTTP/2流连接?

    如今 HTTP 2 的性能正在不断提高 最新版本的 Node js 很好地支持了 HTTP 2 https nodejs org api http2 html https nodejs org api http2 html 但我不知道如何在
  • 如何在Sequelize中配置一对多关系?

    我目前正在使用 Express 和 Sequelize MySQL 想知道解决这个问题的最佳方法是什么 如果这是一个基本问题 我很抱歉 因为我对 Sequelize 甚至 SQL 数据库都很陌生 我有一个模型User像这样 export d
  • 无法在 Sequelize 迁移中执行原始查询

    我正在尝试使用 Sequelize 迁移更新我的数据库 因此我尝试编写这样的 Sequelize 迁移 use strict module exports up queryInterface Sequelize migration gt q
  • 如何在Electron App中调用C# dll方法?

    我有一个电子应用程序 可以从读卡器读取信用卡详细信息 他们提供了一个 c dll 来与应用程序交互 我不知道如何从电子应用程序读取 dll 方法 首先使用以下命令检查 dll 中公开的函数依赖步行者 http www dependencyw
  • 检查用户是否已从 Node.js(云功能)登录 Firebase Auth

    我正在尝试在 Node js 上创建 Express 动态网页 我想在路径上的服务器 Firebase Cloud Functions 上执行以下逻辑 如果客户端已登录 Firebase Auth 则呈现主页my home page htm
  • Node.js ES6如何从模块导出类? [复制]

    这个问题在这里已经有答案了 我正在尝试从 Node js 6 2 0 中的 CommonJS 模块导出 ES6 类 class MyClass class contents here exports MyClass 然后将其导入到另一个模块
  • Node.js 中的 JSON Zip 响应

    我对 node js 还很陌生 我正在尝试发回包含 JSON 结果的 zip 文件 我一直在尝试弄清楚如何去做 但还没有达到预期的结果 我正在使用 NodeJS ExpressJS LocomotiveJS Mongoose 和 Mongo
  • npm i 导致许多 ERESOLVE 问题

    我收到此错误npm i npm ERR code ERESOLVE npm ERR ERESOLVE unable to resolve dependency tree npm ERR npm ERR Found email protect
  • 对数组进行分组并获取计数[重复]

    这个问题在这里已经有答案了 假设我有这样的数组 foo bar foo bar bar bar zoom 我想将其分组 这样我就可以得到这样的计数 foo 2 bar 4 zoom 1 有没有一个实用程序可以做到这一点 只需使用该功能Arr
  • Mongodb 的 Mongoose 与 Mongoose

    我正在学习 NodeJ 要从 NodeJS 连接并使用 MongoDB 我看到很多使用 Monk 或 Mongoose 的示例 这两个库等效吗 它们具有相同的功能还是都有特定的用途 作为 NodeJS 的初学者 我应该使用哪个 以下是使用
  • 猫鼬递归填充

    我已经搜索了一段时间 但没有找到任何好的答案 我有n deep我存储在数据库中并且想要填充的树所有的父母所以最后我得到了完整的树 node parent parent parent 到目前为止 我已达到 2 级 正如我提到的 我需要达到 2
  • 将 JSON var 从路由传递到 ejs

    我在express EJS中有一些代码 1 在 app js 中 创建 mongo 集合对象 app locals userCollection db get userData 2 在user js快速路由文件中 我从这个数据库连接获取数据
  • 是否可以使用 fs.createWriteStream 在文件中间写入文本? (或者一般在 Node.js 中)

    我正在尝试写入文本文件 但不是像appendFile 那样在最后写入或通过替换整个内容 我看到可以选择从 fs createwritestream 的启动参数开始的位置 gt https nodejs org api fs html fs
  • 可以模拟多个并发连接来测试 Nodejs 应用程序

    我有一个简单的node js socket io websockets 应用程序运行 localhost 我想看看它可以处理多少并发连接 是否可以在本地主机本身上模拟多个并发用户 这是我使用 socket io client 的半生尝试 f
  • Node.JS Web 服务器中的安全性

    所以 我正在学习 Node JS 到目前为止我很喜欢它 我已经有几个项目在工作了 我想我可以在其中使用nodejs 不过 我担心安全问题 如果我使用 Node JS http 模块编写自定义 Web 服务器 我是否可能非常容易受到攻击 Ap

随机推荐

  • CSS——快速入门

    CSS的优势 1 内容和表现分离 2 网页结构表现统一 3 样式十分的丰富 4 建议使用独立于HTML的CSS文件 5 利用SEO 容易被搜索引擎收录 style
  • oracle 重复列只显示一次的实现

    CREATE TABLE test ob id VARCHAR 32 ob name VARCHAR 32 INSERT INTO test VALUES A001 A001 a INSERT INTO test VALUES A001 A
  • Golang 变量作用域陷阱 误用短声明导致变量覆盖

    var remember bool false if something remember true 错误 使用remember 在此代码段中 remember 变量永远不会在 if 语句外面变成 true 如果 something 为 t
  • SpringMVC单元测试之MockMVC,模拟登录

    在一些实际开发中 很多情况下需要对数据库进行操作 但是这里的操作就设计到用户权限 所谓权限验证就是拿到用户客户端登录后的token 在代码中进行校验 一般都是在controller层首先进行校验 如果校验成功 则执行之后操作 否则 采取相应
  • Java语言基础

    01 01 计算机基础知识 计算机概述 了解 A 什么是计算机 计算机在生活中的应用举例 计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装
  • Dart基础语言 — 函数 Function

    Dart基础语言 函数 Function 函数定义 int add int x return x 1 调用 add 1 可选参数 int add int x int y int z if y null y 1 if z null z 1 r
  • [!] Unable to determine Swift version for the following pods:

    问题 Unable to determine Swift version for the following pods contact the author or set the SWIFT VERSION attribute pod in
  • Java基础 - XML解析转成Bean以及Bean转成XML(附带案例)

    文章目录 1 JAXB Java Architecturefor XML Binding 面向XML绑定的Java体系结构 1 1 注解 1 2 使用 测试1 反序列化xml文件成JavaBean对象 测试2 序列化普通JavaBean对象
  • java 二进制变量_java变量、二进制、数据类型、原码、补码、反码

    1 变量 1 他 她 我 你 某人 佚名 旺财 X man x 1 您好 它 变量就是自然语言中的代词 2 int age 15 00000000 00000000 00000000 00001111 3 Java 中的变量 a Java是
  • IntelliJ IDEA 2020.3 重大特性

    今天发现 idea 2020 3 版本发布了 那么废话不多说 赶紧更新起来 ps 继续推荐使用 toolbox 进行安装 首先欢迎页变化 1 管理项目 2 配置 IDE 界面 主要就是主题 字体 快捷键等设置 3 插件 已经安装的插件和插件
  • 2023.8.21--微信小程序uni-app

    微信小程序 day1 微信小程序开发 下载微信开发者工具 注册小程序账号 注册小程序账号 填写信息 获取小程序的 AppID 搭建开发环境 认识小程序 小程序的页面布局 小程序组件 标签 view 定义块级区块 相当于 html 中的 di
  • es基础操作

    列出所有索引 列出所有索引 列出所有的数据库 GET cat indices v 添加索引 PUT goods settings 副本数 number of replicas 1 分片数 number of shards 5 删除索引 DE
  • verilog中的操作符

    verilog中的操作运算符如下 1 算数操作符 2 关系操作符 3 相等操作符 4 逻辑操作符 5 按位操作符 6 归约操作符 7 移位操作符 8 条件操作符 9 连接操作符 10 赋值操作符 下面做详细介绍 1 算数操作符 加 减 乘
  • vue3+vite 全局组件注册与使用

    前言 vite和我们的webpack是不同的 这里没办法用require 但是他也有自己的引入文件的方法 是 import meta glob 实现效果 vite方法官方入口 功能 Vite 官方中文文档下一代前端工具链https cn v
  • 张五常的《读书方法》

    首先声明 我要谈的是为知识而读书的方法 不是为考试而读书的方法 后者 香港的学生都是专家 猜题目 背课文之能 世间少有 但为知识而读书可以帮助考试 为考试而读书却未必可助知识的增长 知识是读书的目的 An End 考试只是一个方法 A Me
  • react antd里面的Popover属性content怎么循环写内容,代码展示

    可以使用Antd中的Popover组件 来循环渲染内容 例如 const list name 张三 age 18 name 李四 age 21 return
  • 动画状态机Animator-Unity3d

    该模型一直处于奔跑状态 点击跳跃则跳跃一次后回到奔跑状态 点击攻击后则攻击一次回到奔跑状态 控制代码如下 using UnityEngine using System Collections 该人物一直处于奔跑状态 点击跳跃则跳跃一次后回到
  • 前端工具集合(js框架、ui框架、开发工具...)

    vue3 vue3官网 Vue js pc端开发ui框架 element plus 一个 Vue 3 UI 框架 Element Plus 移动端ui框架 vant Vant Mobile UI Components built on Vu
  • [Unity3D]场景间切换与数据传递(以及物体删除技巧)

    Unity3D 场景间切换与数据传递 以及物体删除技巧 2009 09 16 15 03 47 分类 Unity3D 举报 字号 订阅 先介绍一些基本函数 具体用法自己查文档 1 场景切换 Application LoadLevel Lev
  • node.js基础学习

    什么是node 简单来说 node是JS的一种运行环境 在此之前 我们都知道JS可以在浏览器中运行 可以为网页添加各种交互 因此 浏览器也是JS的运行环境 随着Chrome浏览器的发布 带来了全新的V8引擎 经过多年的发展和优化 性能和安全