node.js 学习笔记4

GET请求和POST请求

GET请求发生的场景:

1.在浏览器地址栏输入网址,然后点击回车,会给该网址发送GET请求

2.点击a标签链接,会给a标签绑定的URL发送GET请求

3.LINK标签引入的CSS,如果CSS是URL,会给该URL发送GET请求

4.script标签引入的js,如果js是URL,会给该URL发送GET请求

5.video/audio引入多媒体,如果引入地址是URL,会给该URL发送GET请求

6.img标签引入图片,如果地址绑定是URL,会给该URL发送GET请求

7.form标签中的method为GET时

8.ajax中的get请求

POST请求发生的场景:

1.ajax的POST请求

2.form标签中的method为POST

3。前后端接口请求,前端向后端传数据时,一般是POST

GET请求和POST请求的对比:

1.GET请求一般用来获取数据,POST请求主要用来提交数据(一般是这样,但是也可以用GET提交数据)

2.参数位置:GET请求参数一般在URL内,以params的形式传输。POST的请求则会放到请求体里,是payload的形式(一般是这样,但是用法也可以互换)

3.安全:POST相对GET安全一些。GET会在URL地址里暴露一些信息(相对来说,如果抓HTTP请求,对请求体进行分析,也能看到POST传输的数据)

4.请求大小:GET由于需要把信息放到URL,一般不会超过2K。POST则可以传输更多信息。

模块化

随着项目的功能加多,项目复杂性也会变高,代码量也会越来越高,如果把代码都放在一个地方,不便于维护和阅读。

基于这些问题,把一个复杂的文件,按照一定的规则拆分成多个文件,对其进行管理,这就是模块化的思想。

拆分出的每一个文件都是一个模块。最后再把模块按照一定的规则组合起来,完成同样的功能效果。

模块内部的数据是该模块私有的,但是模块可以通过暴露的方式把自己的数据交给其他模块使用。

项目模块化

在编写项目时,项目代码是按照模块化的思想来写的,这个项目就是一个模块化的项目。

模块化优点

1.高复用性(模块化代码可以暴露给其他模块使用)

2.高维护性(当项目需要多人开发时,多人对同一个文件进行编辑会发生频繁的冲突。在对项目进行升级或者修复时,也可以按模块进行)

3.可阅读性(模块化项目便于管理和阅读)

4.缓解命名冲突(对于单文件模式,一个文件内部不能包含一样的命名,但是如果使用模块化思想,则可以通过命名空间等方式让不同的变量在各自的空间内可以同名)

简单例子

a.js

javascript 复制代码
function aMethod(){
    console.log('a------')
}

module.exports = aMethod

b.js

javascript 复制代码
const aMethod = require('./a.js')

console.log(aMethod)

aMethod()

模块的暴露与导入

暴露数据

使用module.exports可以默认暴露函数,但是,如果一个模块中有两个函数,我想同时暴露两个函数,应该如何做呢?

1.一个方法是默认暴露一个对象,对象中包含这两个方法

a.js

javascript 复制代码
function aMethod(){
    console.log('a------')
}

function aMethod2(){
    console.log('have a nice day : )')
}

module.exports = {
    aMethod,
    aMethod2
}

b.js

javascript 复制代码
const aMethod = require('./a.js')

console.log(aMethod)

aMethod.aMethod()
aMethod.aMethod2()

2.一个是使用exports.暴露方法 exports.属性名 = 属性值,该方法的效果和默认暴露是一样的,在js内部,存在关系exports = module.exports = {},而require在返回值时,返回的是module.exports的值。

当通过exports.属性名 = 属性值 操作时,实际上是往module.exports绑定的对象里添加方法。所以不要通过exports = 这样的语法来对外暴露,它并不会生效。

a.js

javascript 复制代码
function aMethod(){
    console.log('a------')
}

function aMethod2(){
    console.log('have a nice day : )')
}

exports.aMethod = aMethod
exports.aMethod2 = aMethod2

b.js

javascript 复制代码
const aMethod = require('./a.js')

console.log(aMethod)

aMethod.aMethod()
aMethod.aMethod2()

导入模块

导入模块时,是通过require方法导入。其用法有一些注意事项:

1.自己定义的模块,在require时,建议写相对路径。

2.js和json导入的模块,可以不写后缀,c/c++编写的node扩展文件也可以不写后缀。对于js和json,是先找js,后找json。所以如果一个路径下同时存在同名的js和json文件,然后省略后缀require,会引入js对应的文件。

3.如果导入其他类型的文件,会按照js文件进行处理。

4.如果导入的路径是一个文件夹,会默认寻找这个文件夹下面的package.json文件中的main属性对应的文件,如果这个文件存在,则会导入这个文件。如果main属性不存在,或者package.json不存在,则会检测index.js和index.json。如果都没有,则会报错。

引入文件夹,且配置了package.json里的main:

如果引入文件,并且找不到package.json里的main和index.js和index.json:

5.导入node.js内置的模块时,直接require模块名即可,不需要填写相对路径。

6.module.exports、exports、require都是CommonJS模块化规范,node.js实现了CommonJS模块化规范。

require导入文件时发生了什么:

当使用require导入自己定义的模块时,会发生什么呢?(该流程只针对于导入自己定义的其他模块,对于内置模块或者第三名模块不适用)

  1. 将相对路径转为绝对路径,获取模板文件的地址

  2. 缓存检测(检测该模块是否存在缓存)

  3. 读取目标文件代码

  4. 将目标文件代码包裹为一个函数并执行(自执行函数),通过arguments.callee.toString()可以查看自执行函数

javascript 复制代码
const test = {
    a : 1
}

module.exports = test

//对于该文件中的代码,他们其实是被包裹在一个函数中的
//通过arguments.callee可以获得这个函数,
// 然后.toString(),可以打印函数体
console.log(arguments.callee)
console.log(arguments.callee.toString())
  1. 缓存模块的值

  2. 返回module.exports的值

伪代码示例:

javascript 复制代码
function require(file){
    //将相对路径转为绝对路径
    let absolutePath = Path2D.resolve(__dirname,file)

    //缓存检测,检测之前是否已经require过这个文件
    //如果require过,直接返回之前的返回值,
    //如果没有再执行文件里的代码
    if(caches[absolutePath]){ //这里是伪代码写法,表示从缓存中读取
        return caches[absolutePath]
    }

    //没有缓存,读取文件代码并执行
    let code = fs.readFileSync(absolutePath).toString()
    (
        //这里用伪代码模仿js包裹函数
        function( exports, require, module, __filename, __dirname ){
            ...
            读取的文件代码
            ...


        }
    )(exports, require, module, __filename, __dirname)

    //缓存结果
    caches[absolutePath] = 模块对象

    //返回module.exports
    return module.exports
}

CommonJS模块化规范

module.exports exports require都是CommonJS模块化规范中规定的内容,

node.js实现了CommonJS

CommonJS是一个规范,CommonJS与Node.js就像JavaScript与ECMAScript,即CommonJS是模块化代码的规范,而Node.js对该规范做了实现。ECMAScript是标准,JavaScript也是对该标准进行了实现。

包管理工具

包,package,是一组特定功能的源码集合。

通俗一点来说,包是可以实现某个功能的源码,下载包之后,就可以直接使用这个包已经实现的功能及方法。

包管理工具

管理包的应用软件。在实际项目中,可能会下载使用非常多的包,使用包管理工具,可以对包进行下载安装、更新、删除、上传等操作,能够快速开发项目、提升开发效率。

包管理工具是通用的概念,不是前端或者后端独有的。

常用的包管理工具

对于前端来说,常用的包管理工具有:

npm

pnpm

cnpm

yarm

npm

npm全称Node Package Manager,即Node包管理工具。

npm是node.js官方内置的包管理工具

npm的安装

在安装node.js时,会自动安装npm,所以一般不需要单独安装npm。

通过npm -v可以查看npm版本。如果想管理npm版本,可以通过nvm来进行。

npm初始化包

npm init

在需要初始化包的目录下敲npm init并按回车,即可初始化工具包。

初始化的意思是说,npm会自动创建一个package.json文件用于对包进行管理和配置。在脚手架项目里,直接敲npm init,不需要配置就可以,但是在空目录下敲npm init,则会进入初始的配置流程:

package name package的名字

version 版本

description 对包进行描述

entry point 入口点

test command 测试命令

git repository 仓库地址

keywords 关键字

author 作者

license 开源证书

给这些值配置好之后,会自动生成对应的配置代码:

敲npm init并填写配置:

然后会生成package.json的初始化配置,并让你确认,确认之后,目录下就会多出对应的package.json文件:

在对package.json进行初始化配置时,需要注意:

  1. package name不能使用中文和大写,默认值是文件夹的名称。所以文件夹名称也不能使用中文和大写

  2. version 版本号要求使用x.x.x的格式,并且x必须是数字

  3. license 证书,证书与MIT证书功能是相同的,证书这里先不展开学习了,之后会单独开一个博文讲证书

  4. package.json可以手动创建与修改,也就是说,如果你想全手动创建,也可以不npm init

  5. 使用 npm init -y或者 npm init --yes可以快速创建package.json,跳过配置环节,生成默认的配置

搜索npm包

有时候,我们想往项目里添加一个功能,但是可能我们由于并不知道有哪些包而感到迷茫,如何搜索npm包呢?

一个方法是在终端或者命令行输入npm s 关键字,或者npm search 关键字。

另一个方法是在相关网址上对npm包进行查询:https://www.npmjs.com/

下载npm包

通过语法 npm install 包名 或者npm i 包名 可以下载包。

在下载包之前,需要对项目文件先进行初始化,保证已经有package.json文件。

当敲完下载命令之后,会对远端的地址进行请求,因此该命令需要联网。

下载包之后,文件目录下会多一个package-lock.json文件,该文件用于固定包的版本信息,它可以使一个包在当前安装和下次安装时是一个版本。

导入npm包

使用require(包名) 导入包

当在package.json安装一个包之后,该包称为package.json的一个依赖。

package.json(我们自己的包A)里安装了别的包B,一般说包B是A的一个依赖包,或者说A依赖B。

使用npm包

按照包的用法说明文档使用包

require导入npm包的流程

上文写了require导入自定义模块的流程,对于使用npm安装并导入的包,当require时会发生什么呢?

  1. 在当前文件夹下的node_modules中寻找同名的文件夹,如果找到了,就对该文件夹中的内容进行导入。

比如我使用const test = require('test')导入npm包test,

实际上导入的是当前目录下的'./node_modules/test',也就是说下列两种语法是等价的:

javascript 复制代码
const test = require('test')

const test = require('./node_modules/test')

然后,其实这个说法并不严谨,因为require并不是导入对应文件夹下的全部文件,它导入的是package.json中配置的文件夹下的某个具体的路径。所以其实最后寻找到的是这个路径:

javascript 复制代码
const test = require('./node_modules/test/配置文件中对应的文件夹下的具体路径')

以uuid为例:

最后引入的其实是,两个引入在本例中是一样的:

javascript 复制代码
const uuid = require('uuid')

console.log(uuid)

const uuid2 = require('./node_modules/uuid/dist/index')

console.log(uuid2)
  1. 在上级目录下的node_modules中寻找同名文件夹,直到寻找到根目录。

与直接写相对路径来说不同,写require(包名)时,如果在当前文件夹的node_modules下找不到对应的路径,会往上寻找,直到根目录。

相关推荐
汉堡包0012 小时前
【网安基础】--Spring/Spring Boot RCE 解析与 Shiro 反序列化漏洞的关联(包括简易加密方式梳理)
学习·安全·spring·信息安全
小龙2 小时前
【学习笔记】PyTorch 中.pth文件格式解析与可视化
人工智能·pytorch·笔记·学习
Gavin在路上2 小时前
AI学习之AI应用框架选型篇
人工智能·学习
峰顶听歌的鲸鱼2 小时前
16.docker:存储
运维·笔记·docker·容器·云计算
week_泽2 小时前
OpenCV图像拼接实践笔记(第一部分)
人工智能·笔记·opencv
贺今宵2 小时前
安装sqlite3报错找不到c++/python/nodegyp错误,electron-vite,下载Visual Studio,配置vc环境变量
electron·sqlite·node.js
暖阳之下2 小时前
学习周报二十八
学习
BahTiYar_2 小时前
ctfshow Web应用安全与防护系列
笔记·web安全
七月七332 小时前
半小时搞定GitHub学生认证
笔记·github