NodeJS笔记

一、 入门

1.1 概念

        运行在服务器端的js

        是一个基于Chrome V8引擎的JavaScript代码运行环境

1.2 作用

        提供了js的运行环境(提供了很多内置模块)

        可以通过js开发后台

1.3 组成

        ECMAScript(和js基础语法一样)

        内置模块

        第三方模块

其他

        清空控制台 cls

        终止服务 ctrl c

        终端运行 node .\demo.js

        抓包(浏览器 > 检查 > 网络)

二、模块化

2.1 概念

        把代码进行模块化拆分。也是封装思想,类似函数(方法),都是对代码的封装

        模块化是把代码放在一个单独的js文件中,可跨文件使用

2.2 好处

        提高代码的复用性,可维护性,按需加载,便于协同开发

2.3 分类

        内置模块(node官方提供)

                fs 文件相关模块

                path 路径相关模块

                http 服务器相关

        第三方模块(第三方开发 官方提供 需下载)

                express 路由,可以快速构建web应用

                mysql 可以通过js代码操作mysql数据库

        自定义模块( 用户自己创建的每一个js文件 都是)

2.4 使用

        写一个js文件

                创建一个自定义模块

        通过require(路径)方法加载自定义模块

                把写好的模块复制进去

2.5 模块作用域

        解决了全局变量污染问题:想跨模块使用变量和方法,需先导出再导入

引入模块规范

模块1.js

        let num = 10;
        module.exports.num = num //导出

模块2.js

        let num = 20;
        module.exports.num = num //导出(module可省略)

引入.js(引入,接收,使用)

        const r1 = require("./模块1");
        const r2 = require("./模块2");
        console.log(r1.num);
        console.log(r2.num);

解构引入

        //导出.js
        module.exports = { num, fun };
        //导入.js
        const { num, fun } = require("./导出");

2.6 模块间共享

module对象

        每个自定义模块都有一个module对象,存储了和当前模块相关的信息

        exports:{} //用来存储导出数据,默认为空对象

module.exports对象(常用)

        本质上也是一个属性,值可以是对象,亦可以是方法

        作用:将模块中的成员共享出去, 供外界通过require( ) 方法导入自定义模块, 拿到共享的数据并使用

        导入模块的结果 以导入文件中module.exports指向的对象为主

        查看:console.log(module.exports)

exports对象(不建议)

        module.export === exports

        如果指向新的对象(exports = { }),两者值就不同了

module.exports 与 exports 原理

  • module.export === exports
  • 不同的变量,指向同一地址.
  • 使用{ }赋值,会改变引用地址,此时导出结果以module.export为准
  • 使用 " . " 赋值 引用地址不变
  • module.exports = exports 赋 地址 值

三、内置模块

3.1 fs模块

导入         const fs = require("fs")

调用方法         读写可嵌套

//异步读取 
fs.readFile(filename[, options], callback)
fs.readFile("file/a.txt", "utf-8", (err, data) => {
    if (err) {
        console.log("读取失败:" + err);
        return;
    }
    console.log("读取成功:" + data);
});

//异步写入 
fs.writeFile(filename, data[, options], callback)
fs.writeFile("file/b.txt", "写入数据", (err) => {
    if (err) {
        console.log("写入失败:" + err);
        return;
    }
    console.log("写入成功!");
});

3.2 path模块

导入

        const path = require("path")

直接使用

        __filename 获取当前文件所在绝对路径

        console.log(__filename);

        __dirname 获取当前文件所在目录

方法

  1. path.dirname(p) //返回路径中代表文件夹的部分
  2. path.join([path1][, path2][, ...]) //连接路径
  3. path.extname(p) //返回文件后缀名 如 .txt
  4. path.basename(p) //返回文件名(含后缀)
  5. path.basename(p, '.js'])//返回文件名(不含后缀)

3.3 http模块

//1. 导入http模块
const http = require("http");

//2. 创建web服务器
const server = http.createServer();

//3. 处理用户请求(为服务器绑定一个request事件,监听客户端发来的请求,做出响应)
server.on("request", (req, res) => {
  //req请求对象 res响应对象
  //程序员可以在函数体中操作 拿到的请求对象和响应对象
  res.setHeader("content-type", "text/html;charset=utf-8");
  res.end("<h1>hello中文</h1><hr>");
});
//4. 监听端口(发送请求所用端口需要与此一致)
server.listen(3000, function () {
    console.log("服务器已经启动,访问:http://127.0.0.1:3000");
});

四、包

4.1 概念

第三方个人或团队开发的,可免费供其他人使用

npm

4.2 好处

基于内置模块封装,提供一个更高级更方便的API,提高开发效率

4.3 npm 包管理工具

版本         npm -v

安装         npm i 包名

卸载         npm uninstall 包名

4.4 nrm 镜像管理工具

npm install nrm -g //安装镜像管理工具 -g全局安装
nrm ls //列出所有镜像
nrm user taobao //使用淘宝的镜像

4.5 package规范

组成

node-modules 已安装的包

package.json 包配置文件

        name:包名
        version:版本号
        main:包的入口路径

dist 发布目录

src 源码目录

规范

包必须以单独目录出现

顶级目录下要有package.json配置文件, 且必须包含属性(name包名, version版本号, main包入口)

手写一个包

1)建文件夹 node_modules\clac

2)初始化文件夹

                cd node_modules\calc
                npm ini -y

3)创建包的目录结构 calc

                ├── dist 发布目录

                │ └── index.js 入口文件

                ├── src 存储源码

                └── package.json("main": "dist/index.js")

4)编写源码(src下)

                创建add.js文件,加法功能,module.exports导出

5)编写头文件(dist/index.js)

                先全部导入 再全部导出

                就像书本目录。将来只需引入头文件 即可引入整个源码中的文件

6)使用自定义的包

                导入   const calc = require("calc");

                使用   const sum = calc.add(10, 20);

模块加载机制

require("calc")步骤

        nodejs假设它是一个内置模块,进node安装路径找

        进当前目录node_modules找

                找同名js文件

                找同名文件夹,从其中package.json文件的main属性,确定模块的入口文件

                        失败 → 用文件夹根目录的 index.js

注意

        模块第一次加载后会缓存(多次require不会被重复加载)

        优先从缓冲中加载

        内置模块(官方提供)加载优先级最高

加载规则

        先内置模块

        node_modules中找

                同名js文件

                同名文件夹

                        package.json中main指定的入口文件

                        同名文件夹/index.js

五、服务器

5.1 概念

        高性能、电脑(集群)

        负责存储、对外提供资源,永不关机

        客户端:消费资源

5.2 网络通讯三要素

IP

        本地主机: 127.0.0.1 的域名 localhost

        域名服务器:DNS

                提供IP地址和域名间转换服务的 服务器

        设备在网络中的唯一标识

端口

        程序在设备中的唯一标识(比如餐厅中的某一个窗口)

http协议

        规定了浏览器和服务器间的传输形式

        浏览器发送什么样的数据给服务器,服务器才能解析

        服务器发送什么样的数据给浏览器,浏览器才能解析

5.3 客户端与服务器通信过程

5.4 URL地址

概念

        统一资源定位符,可以定位互联网上的唯一一个资源https://detail.tmall.com:80/item.htm?id=653413567689

组成

        通讯协议 https://

        ip/域名 detail.tmall.com

        端口 80(一般默认)

        资源名称(存放位置) item.htm?id=653413567689

5.5 HTTP协议

超文本传输协议

作用

        规定了浏览器和服务器间的传输形式

        浏览器发送什么样的数据给服务器,服务器才能解析

        服务器发送什么样的数据给浏览器,浏览器才能解析

特点

        基于请求和响应模型

        先有请求 再有响应

        请求和响应 成对出现

                  请求成功,200

                  请求失败,404,500

5.6 请求/响应消息

请求消息

概念:客户端给服务器的消息,告诉服务器,我浏览器的一些信息

组成

        请求行

                请求方式
                请求URI(统一资源标识符,前面没协议)
                版本协议

        请求头(键值对)

                user-agent:浏览器版本号

                content-type:发给服务器的数据格式

                accept:浏览器能够支持的返回内容类型

                accept-language:浏览器期望获取自然语言的顺序

        请求体

                post请求才有

常见请求方式

        get 查

                数据拼接在地址栏后,不安全,数据量少

                一般用于从服务器获取数据

        post 增

                数据保存在请求体中,相对安全,数据量大

                一般向服务器提交数据(表单、文件上传下载)

响应消息

概念

        服务器发给客户端的信息(数据类型及特点)

组成

        响应行

                格式:协议版本 状态码 状态码描述

        响应头

                content-type:发送数据的类型和编码

                content-length:发给浏览器内容的字节长度

        响应体

                显示到页面正文的内容

常用的响应状态码

  • 2xx 成功 200
  • 3xx 重定向 302
  • 4xx 客户端错误 404
  • 5xx 服务端错误 500

restful风格

        通过不同请求方式,调用不同方法,实现不同功能

        请求方法

  •                 post     增
  •                 delete   删
  •                 put      改
  •                 get      查

5.7 请求/响应对象

由来

请求响应消息 封装为 请求响应对象(请求/响应消息 都是字符串,操作麻烦)

请求对象(request对象)

封装请求消息,主要提供get方法(获取数据)

        请求方式(request.getMethod)

        请求体 (请求体rul:req.url)

响应对象(response对象)

封装响应消息,设置数据(响应状态码)

        设置响应头 res.setHeader()

        res.setHeader("content-type", "text/html;charset=utf-8");

                             引号内不可乱加空格!

        设置响应体 res.send()

5.8 🟢最简单的服务

//1. 导入http模块
const http = require("http");

//2. 创建web服务器
const server = http.createServer();

//3. 处理用户请求(为服务器绑定一个request事件,监听客户端发来的请求,做出响应)
server.on("request", (req, res) => {
  //req请求对象 res响应对象
  //程序员可以在函数体中操作 拿到的请求对象和响应对象
  res.setHeader("content-type", "text/html;charset=utf-8");
  res.end("<h1>hello中文</h1><hr>");
});
//4. 监听端口(发送请求所用端口需要与此一致)
server.listen(3000, function () {
    console.log("服务器已经启动,访问:http://127.0.0.1:3000");
});

5.9 手写web服务

1)基本web服务

        1. 导入模块

        2. 创建web服务器

        3. 绑定事件,处理请求

        4. 设置端口,进行监听

2)处理中文乱码

原因: 前后编码不一致

        服务器发送数据:使用ISO-8859-1(拉丁文),不支持中文

        浏览器接收数据并解析:中文的window使用GBK(国标)

解决: res.setHeader("content-type", "text/html;charset=utf-8");

        使用响应对象,设置响应头,统一编码。

        告诉浏览器发送数据格式是utf-8,浏览器接收后以utf-8编码解析

3)处理路由

路由:根据不同的请求url,响应不同数据

  • http://localhost:3000/index 响应首页
  • /list 响应列表页
  • /detail 响应详情页

http://      localhost      : 3000        /detail           ?           id=1

协议          ip域名          端口        pathname                 query

思路:

        通过请求对象req中的url属性,获取请求的url

        通过url内置模块,解析获取的url,得url对象

        从url对象的pathname属性 拿值

url.parse(urlStr, true) 参数

        false(默认) query值为字符串 query:'id=1'

        true                 query是对象 query: [Object: null prototype] { id: '1' }

简写(解构赋值)const {pathname, query} = url.parse(req.url, true);

Url {
  	protocol: null,
    slashes: null,
    auth: null,
    host: null,
    port: null,
    hostname: null,
    hash: null,
    search: '?id=1',
    query: [Object: null prototype] { id: '1' }, //参2true→对象,false→字符串
  	pathname: '/detail',
    path: '/detail?id=1',
    href: '/detail?id=1'
}

4)处理get请求

需求:获取 http://localhost:3000/detail?id=1 后面拼接的参数 id=1

思路

前提:解析了url

        const url = require("url");
        server.on("request", (req, res) => {
        const { pathname, query } = url.parse(req.url, true);
        }

先判断请求路径是否已/detail开头

        if (pathname == "/detail")
        //根据不同url(pathname值)响应不同数据

是:判断请求方式是否为get

                if (req.method == "GET") //大写!

是:解析获取的url 拿到query属性的值

                console.log(query.id);

应用:查询单个数据

5)处理post请求

需求:模拟登录/新增

        请求url: http://localhost:3000/

        请求体: username=zs&password=123

思路

        前提:解析了url

        const url = require("url");
        server.on("request", (req, res) => {
        const { pathname, query } = url.parse(req.url, true);
        }

        路径

        if (pathname == "/" || pathname == "/index")

        是否为POST请求

        if (req.method == "POST")

        监听request两个事件

                        data 数据变化 事件,累加

                        end 数据接收完成 事件,打印

//data事件:服务器接收到post数据变化的时候 (用空字符串接收一点点传过来的数据)!!!
//end事件:服务器接收完post提交的数据时调用
  let postData = "";
  req.on("data", (data) => {
      postData += data;
  });
  req.on("end", () => {
      const obj = qs.parse(postData);
      console.log(obj); //对象
      console.log(postData); //字符串

6)封装post请求(Promise)

原因

        获取post请求的数据是固定写法,经常用到

        获取请求数据是异步操作,推荐用promise封装

步骤

        定义一个方法(返回一个promise对象)

        创建promise对象,需传一个函数

        将要封装的代码放在函数体中

        代码结果 放在resolve() 方法的参数中 返回(将来用then() 可以拿到)

执行流程

        调用封装的getPostData() 得到promise对象

        调用promise的then()方法,从第一个函数的参数data 拿到promise对象中函数执行的结果

        打印

源码

7)处理静态资源(读文件并响应)

需求

        当浏览器地址栏输入 http://localhost:3000/

        显示新闻首页

思路

        1. 解析请求路径,判断pathname是(/或者/index)

        2. 读取public路径下的文件,并返回(同步读取!)

源码

const url = require('url');
const path = require('path');
const fs = require('fs');

//定义一个方法,用于读取静态文件
function readStaticFile(filename){
    //获取文件的真实路径
    const filePath = path.join(__dirname,'public/',filename) 
    //同步的读取文件(一定调用readFileSync方法)
    return  fs.readFileSync(filePath)
}

if(pathname == '/'){
        //调用方法读取文件
        const fileDate =  readStaticFile('news.html')
        res.end(fileDate)
}

🟢 源码

//1.导入模块
const http = require("http");
const url = require("url");
const qs = require("querystring"); //POST请求
const path = require('path');
const fs = require('fs');

//2. 创建web服务器
const server = http.createServer();

//用函数封装POST请求(promise)
function getPostData(req) {
    return new Promise((resolve, reject) => {
        let postData = ''

        req.on('data', data => { postData += data })
        req.on('end', () => {
            resolve(qs.parse(postData))//调用then()拿结果
        })
    })
}

//3. 处理用户请求(为服务器绑定一个request事件,监听客户端发来的请求,做出响应)
server.on("request", (req, res) => {
    //req请求对象 res响应对象
    res.setHeader("content-type", "text/html;charset=utf-8"); //编码

    const { pathname, query } = url.parse(req.url, true);//解构赋值

    //根据不同url(pathname值)响应不同数据
    if (pathname == "/" || pathname == "/index") {
        //处理POST请求
        if (req.method == "POST") {
            //调用POST封装的promise对象 then方法
            getPostData(req).then(
                //获取并处理解析后的请求结果
                (data) => { console.log(data); },
            )
        }
        res.end("首页");
    } else if (pathname == "/detail") {
        //处理GET请求
        if (req.method == "GET") {
            console.log(query);
            console.log(query.id);
        }
        //读取静态页面
        res.end(fs.readFileSync('./detail.html'))
    } else {
        res.writeHead(404);
        res.end("404 not found");
    }
});

//4. 监听端口(发送请求所用端口需要与此一致)
server.listen(3000, function () {
    console.log("服务器已经启动,访问:http://127.0.0.1:3000");
});

5.10 REST client(插件)

空行要规范!

### 模拟GET请求
GET http://localhost:3000/detail?id=1 HTTP/1.1
### 模拟post请求(请求行 请求头 请求空行 请求体)
POST http://localhost:3000/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=zhangsan&password=123

5.11 nodemon使用

相当于node升级版,监控文件变化、自动重启

安装 npm i nodemon -g

使用 nodemon ./demo.js

        报错(nodemon : 无法加载文件)

                powerShell(管理员),输入set-ExecutionPolicy RemoteSigned

              (设定 powershell 脚本的安全策略。即决定什么 .ps 脚本可以被运行,什么脚本不允许运行)

5.12 端口占用解决

cmd > netstat -anno 找到端口对应进程的PID,去任务管理器详情页关闭

六、接口编程

6.1 接口概念:一个规范

6.2 接口文档

即接口的说明文档,是调用接口(请求后台数据的)依据

包含对接口的url、参数、输出内容的说明

可以方便知道接口作用、如何调用

6.3 接口编程

前后都安按约定好的规则(接口文档)进行编程,编写后进行联调

具体体现:http协议中的请求和响应

前端:发送请求

        请求url

        请求方式

        请求参数

后端:做出响应

        响应状态码

        状态码描述

        返回具体的数据

6.4 好处:实现前后端分离,便于协同开发

七、restful接口设计

7.1 概念

一种接口设计风格,主要用于有客户端和服务端交互的文件

7.2 接口设计六要素

前端

        资源路径:请求url(http://127.0.0.1:3000/login)

        HTTP动词:请求方式(get)

        过滤信息:请求参数(uname=zs&password=123)

后台

        状态码(status-code):(登陆成功:200)

        错误信息(error):(服务器内部错误)

        返回结果(data或result):返回登录用户相关信息

7.3 常用HTTP动词

GET:获取资源(一或多)

POST:新增

PUT:修改

DELETE:删除

7.4 restful接口体验

1)json-server概念

一个快速成形的restful接口服务,使用json-server可以快速搭建一个RESTful服务端

2)json-server概念搭建服务端

安装                      npm i json-server -g

新建data.json做数据源

        {
        "users": [
        {"id": 1, "name": "xiaoming", "age": 20},
        {"id": 2, "name": "xiaomei", "age": 18}
        ]
        }

启动服务端         ​​​​​​​json-server -w .\data.json

3)🟢模拟前端(发送restful风格请求)

### 查询所有	
GET http://localhost:3000/users HTTP/1.1
### 查询一个	
GET http://localhost:3000/users?id=2 HTTP/1.1 
### 查询一个(常用)	
GET http://localhost:3000/users/3  HTTP/1.1
### 查询多个(不能id与name混&查)
GET http://localhost:3000/users?id=2&id=3 HTTP/1.1 

### 新增
POST http://localhost:3000/users HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=weiyang&age=22

### 修改
PUT http://localhost:3000/users/5 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=yang&age=23

### 删除
DELETE http://localhost:3000/users/4 HTTP/1.1

八、AJAX

8.1 概念:异步的js和xml技术

xml

        <user>
        <uname>张三</uname>
        <age>23</age>
        </user>

json

        {"username":"张三","age":"123"}

8.2 作用

请求后台数据(实现网页和服务器间数据交换)

局部刷新(更新部分网页内容)

一般作为前后端分离中请求后台数据的解决方案

8.3 同步异步

同步:同一时间做一件事(阻塞式)

异步:同一时间可做多件事(非阻塞式,多线程)

8.4 应用场景

百度注册(失去焦点时校验用户是否被注册)

百度搜索框(根据输入提示不同信息)

百度地图(按需加载)

8.5 🟢jquery的ajax

$.ajax({
  url:'',//请求的地址
  type:'',//请求方式
  data:{},//请求的参数
  dataType:'',//返回的数据格式(默认是json,可以不用写)
  success:function(res){},//成功的回调函数
  error:function(err){},//失败的回调函数
})
$.get(url, [data], [callback], [type])   //后面3个参数是可选的
    // url:待载入页面的URL地址
    // data:待发送 Key/value 参数。
    // callback:载入成功时回调函数。
    // type:返回内容格式,xml, html, script, json, text, _default
$.post(url, [data], [callback], [type])   //后面3个参数是可选的
    // url:待载入页面的URL地址
    // data:待发送 Key/value 参数。
    // callback:载入成功时回调函数。
    // type:返回内容格式,xml, html, script, json, text, _default
$.ajax({
    url:'http://localhost:3000/users', 
    type:'post',
    data:{name:'zs',age:22}, 
    success:function(data){ console.log(data); }
})
$.ajax({
    url:'http://localhost:3000/users/5',
    type:'delete',
    success:function(data){ console.log(data); }
})
$.ajax({
    url:'http://localhost:3000/users/5',
    type:'put',
    data:{name:'zs',age:20}, 
    success:function(data){ console.log(data); }
})
$.ajax({
    url:'http://localhost:3000/users/2', //设置参数法1
    type:'get',
    // data:{id:2},  //或设置参数法2
    success:function(data){ console.log(data); }
})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

假以时日♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值