NodeJS_笔记

2023年 9月 29日 55.4k 0

模块化与 npm

前端 JS:与浏览器交互

后端 Node.js:在服务器(和系统进行交互)端运行 JS、跨平台

Node 是对 ES 标准一个实现,Node 也是一个 JS 引擎通过 Node 可以使 JS 代码在服务器端执行

Node 仅仅对 ES 标准进行了实现,所以在 Node 中不包含 DoM 和 BOM

Node 中可以使用所有的内建对象

string Number Boolean Math Date RegExp Function object Array

而 BoM 和 DOM 都不能使用

但是可以使用 console 也可以使用定时器( setTimeout () setInterval() )

Node 可以在后台来编写服务器

Node 编写服务器都是单线程的服务器

  • 进程:进程就是一个一个的工作计划(工厂中的车间)
  • 线程:线程是计算机最小的运算单位(工厂中的工人)
    线程是干活的

传统的服务器都是多线程的

  • 每进来一个请求,就创建一个线程去处理请求

Node 的服务器单线程的

  • Node处理请求时是单线程,但是在后台拥有一个 I/O 线程池

模块化

  • Node 中,一个 JS 文件就是一个 模块
  • Node 中,每一个 JS 文件中的 JS 代码都是独立运行在一个函数中,而不是全局作用域,所以一个模块中的变量和函数在其它模块中无法访问

向外部暴露属性或方法 exports.

var x = 'mmmmm1';
var y = 'm11111';


function f() {
    console.log('f');
}

exports.f = f;//暴露函数
exports.a = 'engureguo';//暴露属性
exports.x = x;
var m1 = require('./01.m.js');

console.log(m1);
//{ f: [Function: f], a: 'engureguo', x: 'mmmmm1' }

核心模块:服务器级别的 API,被封装到包中

  • fs 文件系统工具包
  • http 服务器工具包
  • path 处理路径相关
  • os 查看CPU、内存、用户等信息
  • ...

核心模块引入

  • node引擎提供的模块
  • 核心模块标识,就是模块的名字
var fs = require('fs');

文件模块

  • 相对路径,以 . 或 .. 开头
  • 绝对路径

全局对象 global,保存全局的 属性和方法

创建全局变量:

a = 0;

global.x = 1;

验证:一个JS文件独立运行在一个函数中,而不是全局作用域,别的模块无法访问

console.log(arguments);//函数入参

console.log(arguments.callee);//当前执行的函数对象
console.log(arguments.callee + "");//查看函数实现

------------------------

function (exports, require, module, __filename, __dirname) {

var m1 = require('./01.m.js');

console.log(arguments);
console.log(arguments.callee + "");

}

实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时传递进了五个实参(global.arguments)

arguments 含义 index
exports 该对象用来将变量或函数暴露到外部 0
require 函数,用来引入外部的模块 1
module 代表当前模块本身,exports 是 module 的属性。module.exports = exports,也可以 module.exports 导出 2
__filename 模块绝对路径 3
__dirname 模块所在文件夹 4
[Arguments] {
  '0': {},
  
  '1': [Function: require] {
    resolve: [Function: resolve] { paths: [Function: paths] },
    main: Module {
      id: '.',
      path: 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws',
      exports: {},
      parent: null,
      filename: 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\demo.js',
      loaded: false,
      children: [Array],
      paths: [Array]
    },
    extensions: [Object: null prototype] {
      '.js': [Function (anonymous)],
      '.json': [Function (anonymous)],
      '.node': [Function (anonymous)]
    },
    cache: [Object: null prototype] {
      'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\demo.js': [Module],
      'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\01.m.js': [Module]
    }
  },
  
  '2': Module {
    id: '.',
    path: 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws',
    exports: {},
    parent: null,
    filename: 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\demo.js',
    loaded: false,
    children: [ [Module] ],
    paths: [
      'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\node_modules',
      'C:\Users\HiWin10\Desktop\notes\其他\node.js\node_modules',
      'C:\Users\HiWin10\Desktop\notes\其他\node_modules',
      'C:\Users\HiWin10\Desktop\notes\node_modules',
      'C:\Users\HiWin10\Desktop\node_modules',
      'C:\Users\HiWin10\node_modules',
      'C:\Users\node_modules',
      'C:\node_modules'
    ]
  },
  
  '3': 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws\demo.js',
  
  '4': 'C:\Users\HiWin10\Desktop\notes\其他\node.js\code-ws'
}

module.exports 与 exports 的区别

module.exports 可以实现 exports 的功能,还可以:

module.exports {
    name: 'engure',
    age: 22,
	say: function() {}
}

栈内存和堆内存

var a = xxx;
var b = a;
b++;
a ? b

基本数据类型保存的数据相互独立,区别于引用类型

exports 指向 module.exports

exports = { } 相当于 exports = new Object(); 相当于修改了指向,是错误的用法

总结:

  • 通过 exports 只能使用 . 的方式向外部暴露对象
  • 通过 module.exports 既可以通过 . 的方式,有可以通过直接赋值 {}

问题:以上是讲师所讲内容,在我的机器上 node 14.17.1,可以通过 exports = {} 进行赋值

实验总结:两者的关系是开始时指向同一个对象,是引用类型,如果其中之一又创建了对象(={},或 =new Object()),那么两者指向不同

版本问题?

package.json,包的描述信息

dependencies 依赖的包

description

devDependencies 开发依赖,开发环境,区别于生产环境

directories

dist

licence

homepage

maintainers

repository

name 模块标识

...

json 文件不能写注释

NPM 包管理器

Node Package Manager

npm -v

npm version

npm search 包名

npm install 包名(install 可以简写为 i

npm init

npm remove 包名 (remove 可以简写为 r

⭐ npm install 包名 --save(安装包并安装到依赖中,--save 可简写为 -S)安装的同时将包设置在 dependencies 中,记录依赖包和他的版本,push到git上时不传 node_modules/ 中的内容

⭐ npm install 安装依赖,自动根据版本下载包

npm install -g 包名 全局安装,一般都是一些工具

如何在一个指定的目录下使用一个 npm 上的包比如 math?

  • 初始化包 npm init (一路回车,包名不允许大写)
  • 安装 math 包 npm install math 此时 math 被安装到 node_modules
  • 创建 index.js,引用并使用,运行 node index.js
  • var math = require('math');
    
    console.log(math.add(100, 200));
    

    CNPM

    下载大包很慢,使用淘宝镜像,China NPM

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    

    cnpm 命令和 npm 一样

    cnpm i express -S
    

    看到下载的文件保存方式和原来的 npm 保存方式不一样。

    使用快捷方式指向包的方式,避免两者的冲突

    node 搜索包的流程?⭐

    node 使用模块名字来引入模块时,首先在当前目录的 node_modules 下寻找,如果找不到会去上一级继续找,如果没有则继续向上找,一直找到根目录,如果找不到则报错

    commonJS 与 ES6

    package.json 中定义 type 字段

  • commonjs 默认,用于 node 环境
  • // util.js
    exports.name = '123';
    exports.age = 22;
    exports.fun = function () {
        console.log('function');
    }
    
    //js.js
    var { name } = require('./util.js')// 通过 { x } 部分引入
    var obj = require('./util.js')  // 全部引入
    console.log(name)
    console.log(obj);
    

    module.exports 与 exports 用法:zhuanlan.zhihu.com/p/87729137

    浏览器端的应用,使用 browserify 进行语法转化

    blog.csdn.net/dreams_deng…

  • es6 规范
  • 大环境所致:技术变革,前后端分离,前端的业务变的越来越复杂。

    es6 让 javascript 第一次支持 module(浏览器环境)

    前提:使用 npm init -y 初始化包,并指定 type: module

    //m1.js
    var name = 'engure';
    var sayHello = function () {
        console.log('hello')
    }
    
    export var name;	// 同名
    export var sayHello;
    
    
    //m2.js
    export default {
        college: 'cup',
        type: 'undergraduate'
    }
    
    
    //app.js
    import { name, sayHello } from './m1.js'
    import * as m1 from './m1.js'
    import obj from './m2.js'
    
    console.log(name);
    console.log(m1);
    console.log(obj)
    

    浏览器端的使用

    
    
    
    
        
        
        
        Document
    
    
    
    
    
        // 定义模块
        			指定type!
            import { name, sayHello } from './m1.js'
            console.log(name)
        
        
        
        // 引入模块
        
    
    

    Buffer 与 fs 模块

    Buffer

    和数组很像,操作方法也相似

    与数组不同的是,它能够存储二进制数据

    不需要引入,Node自带,直接用

    var str = 'Hello Engure!';
    
    //将一个字符串保存到buffer中,
    var buf = Buffer.from(str);
    
    console.log(buf);
    //
    //范围 00~ff, 0000-0000 ~ 1111-1111,以字节为单位
    
    

    buffer 占用的内存:buffer长度个字节

    一个汉字占用 3 个字节

    //
    console.log(Buffer.from('盖特'));
    

    Buffer 简单使用

    所有构造方法都已经废弃了

    Buffer.alloc(size)

    Buffer大小一旦分配,其长度固定不变,是对内存进行直接操作。(区别于数组)

    //数组越界:自动分配空间
    var arr = [1,2,3];
    arr[5] = 5;
    console.log(arr);
    //[ 1, 2, 3, , 5 ]
    

    赋值&取值

    var buf = Buffer.alloc(10);
    buf[0] = 88;
    buf[1] = 255;//ff
    buf[2] = 0xaa;
    buf[3] = 450;//超过255会取低8位
    
    //查看内容
    buf[2]    //默认10进制
    buf[2].toString(16);  //16进制内容
    buf[2].toString(2);   //2进制
    
    //循环
    for (var i=0;i= len 字节的内容
    
    

    创建目录

    fs.mkdir(path [, mode], callback)

    fs.mkdirSync(path [, mode])

    删除目录

    fs.rmdirSync(path)

    fs.rmdir(path, callback)

    文件重命名

    fs.rename(oldPath, newPath, callback)

    fs.rename(oldPath, newPath)

    fs.rename('by.mp3', 'by1.mp3', function (err) {
        if (!err){
            console.log("修改成功!");
        }
    });
    

    不同目录下,文件移动功能

    //不同目录下,类似文件移动功能
    fs.rename('by.mp3', 'F:/by1.mp3', function (err) {
        if (!err){
            console.log("修改成功!");
        }
    });
    

    文件的监视

    fs.watchFile(filename [, options], listener)

    fs.watchFile('f5.txt', function (cur, pre) {
        //console.log(arguments);
        //cur 当前的Stats
        //pre 之前的Stats
        console.log(pre.size, '->', cur.size);
    });
    

    image-20210829113234439

    设置 options.interval 属性,配置轮询频率

    fs.watchFile('f5.txt', {interval: 100}, function (cur, pre) {
        console.log(pre.size, '->', cur.size);
    });
    

    注意:如果设置的太小很消耗性能

    http 模块

    var http = require('http');
    
    var server = http.createServer();
    
    //注册request请求事件
    server.on('request', function () {
        console.log(arguments)
    });
    
    //启动服务器,需要绑定端口号
    server.listen(80, function () {
        console.log("server starting...");
    });
    

    请求处理

    //注册request请求事件,回调函数需要接受两个参数
    //  Request对象,获取客户端的一些信息,比如URL
    //  Responce对象,用来给用户发送响应消息
    server.on('request', function (req, resp) {
        console.log('请求路径 = ' + req.url);
    
    
        //write可以多次,必须以end结束,告诉给客户端写入已经结束了
        resp.write('hello node.js.');
        resp.end();
    });
    

    req.url

    都是以 / 开头,是用户请求的路径

    可以根据请求路径 req.url 响应不同的内容

    server.on('request', function (req, resp) {
        console.log('请求路径 = ' + req.url);
    
        //区别对待不同的请求
        if (req.url == '/' || req.url == '/index.html' || req.url == '/index') {
            //主页
            resp.write('index');
        } else if (req.url == '/hello') {
            //hello页
            resp.write('

    hello bro!

    '); } else { //404 resp.write('page not found'); } resp.end(); });

    js 中字符串的比较 www.w3school.com.cn/js/js_strin…

    Response 中的 Content-Type ⭐⭐

    告诉客户端发送的内容类型

    server.on('request', function (req, resp) {
    
        //告诉对方我发送的数据类型是什么
        resp.setHeader('Content-Type', 'text/plain; ');
        resp.end("hello 小郭")
    
    });
    

    image-20210829122440003

    Content-Type 有哪些类型,表示哪些文件 www.runoob.com/http/http-c…

    Content-Type 默认类型是什么?text/html,会解析响应的html元素

    如果是 text/plain 表示纯文本类型,默认不会解析html元素

    image-20210829123133459

    发送网页

    server.on('request', function (req, resp) {
    
        if (req.url == '/') {
            //发送html文件
            fs.readFile("index.html", function (err, data) {
                if (err) {
                    resp.setHeader('Content-Type', 'text/plain; charset=utf-8');
                    resp.end("文件不存在,请重试")
                } else {
                    resp.setHeader('Content-Type', 'text/html; charset=utf-8');
                    resp.end(data)//参数可以是字符串也可以是Buffer,这里data是Buffer类型
                }
            });
    
        }
    });
    

    发送图片

    server.on('request', function (req, resp) {
    
        if (req.url == '/') {
            //告诉对方我发送的数据类型是什么
            resp.setHeader('Content-Type', 'text/html; charset=utf-8');
            resp.write("hello 小郭")
            resp.write("");
            resp.end()
    
        } else if (req.url == '/img') {
            //发送图片
            resp.setHeader('Content-Type', 'image/jpeg;');//二进制文件(图片、音频)不需要指定编码
    
            var rs = fs.createReadStream('5.jpg');
            rs.once('close', function () {
                resp.end()//真正关闭resp写入
            });
            rs.on('data', function (data) {
                resp.write(data)
            });
    
            //resp.end()异步操作,出错!Error [ERR_STREAM_WRITE_AFTER_END]: write after end
        }
    });
    

    踩坑记录:node http fs.createReadStrem 发送文件 Error ERR_STREAM_WRITE_AFTER_END]: write after end_Engure-CSDN博客

    关于设置 Content-Type:

    不同类型:

    类型 Content-Type
    纯文本 .txt text/plain; charset=utf-8
    html, htm text/plain; charset=utf-8
    .xml text/xml
    .jpg image/jpeg
    .png image/png
    .gif image/gif
    json格式 application/json
    .pdf application/pdf
    .word application/msword

    编码类型:

    • 对于二进制数据,不需要设置 charset
    • 对于文本类型数据 text/* ,需要设置 charset

    链接

    node中文文档 nodejs.cn/

    李立超Node.js(部分)www.bilibili.com/video/BV1bs…

    服务器开发 - 黑马 www.bilibili.com/video/BV1Ns…

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论