02
第二天¶
统计信息:字数 8908 阅读18分钟
01.http-理解http模块的概念及作用¶
服务器和客户端:网络节点中,负责消费资源的电脑就是客户端,负责对外提供网络资源的电脑叫做服务器。一个主机可以同时提供服务并且消费资源。
服务器和普通电脑的区别:安装了 web 服务器软件(Apache等),安装后,提供了服务就是服务器
http 模块是官方提供的,创建 web 服务器的模块。nodejs 中不需要单独的 web 服务器软件 apache,直接使用即可创建服务器,并对外提供 web 服务。
02.http-服务器相关的概念¶
IP: 是互联网中每台计算机的唯一地址(类似于手机号),只有知道对方 IP 的情况下,才能数据通信。互联网中的每台 web 服务器都有 IP 地址,可以使用 ping 查询到某个服务器的地址。本机的 IP 地址是 127.0.0.1。
域名:IP 是一个很长的数字,不便于记忆。为了方便记忆,所以使用一个英文字符串(就是域名)来表示真实的IP。如果在浏览器中输入域名(baidu.com),首先到域名服务器(DNS)中查找IP,然后访问这个IP。域名服务器实际上就是一个域名和IP的键值对查询服务器。实际测试,ping 不同子域名 IP 是不同的结果(baidu.com, fanyi.baidu.com, map.baidu.com)。单独使用 IP 地址也能工作,域名让访问更便捷。127.0.0.1 的域名就是 localhost。
端口号:一个服务器可能同时提供多个服务。为了不冲突,每一个服务都对应唯一的一个端口号。客户端发出的网络请求,通过端口号,可以被不同的 web 服务进行处理。一个端口号不能被多个服务占用,如果一个端口占用了,那么新的web服务会提示另外一个端口开启。默认端口是80,80 端口通常可以省略。
03.http-创建最基本的web服务器¶
创建步骤:导入http模块——创建http对象实例——绑定 request 事件,监听客户端请求——启动
const http = require('http');
const server = http.createSrever();
server.on('request', function(req, res) {
console.log('request event');
// request 是客户端发出的请求对象,可以查看请求的URL和方法
const { url, method } = req;
console.log(url, method);
// response 是服务器相关的对象,可以用于返回数据
res.end(method);
// 如果直接发送中文内容,会显示乱码,应该手动设置返回的编码类型
res.setHeader('Content-Type', 'text/html: charset=utf-8');
});
server.listen(80, () => {
console.log('server is running at localhost:80')
});
04.http-根据不同的url响应不同的html内容¶
实际上就是 urls 模块,根据不同的 URL 设置返回值。
实现思路(先一定把思路理清楚)——这个教程最大的收获是如何分析问题
- 获取请求的URL
- 设置默认的相应内容是404
- 设置请求首页内容
- 设置关于页面内容
- 处理中文乱码
- 返回客户端
const http = require('http');
const server = http.createServer();
server.on('request', function(req, res) {
const url = req.url;
let content = '404 not fount';
if (url === '/' || url === '/index.html') {
content = 'main page';
}
else if (url === '/about.html') {
content = 'about page';
}
res.setHeader('Content-Type', 'text/html: charset=utf-8');
res.end(content);
});
server.listen(80, () => {
console.log('server is running at 80');
})
05.http-时钟web服务器案例¶
web服务器实现思路
- 浏览器输入 URL,发出请求
- web 服务器根据 URL 匹配需要找到的资源
- 查询数据库,获取资源(这里使用fs模块直接读取硬盘的数据,模拟数据库)
- 返回给前端页面,展示
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer();
server.on('request', (req, res) => {
let url = req.url;
// handle default path /
if (url === '/') {
url = './clock/index.html';
}
const fpath = path.join(__dirname, url);
fs.readFile(fpath, 'utf-8', (err, dataStr) => {
if (err) {
return res.end('404 not found');
} else {
res.end(dataStr);
}
});
});
server.listen(80, () => {
console.log('server running at http://127.0.0.1:80');
});
06.模块化-模块化的概念¶
- 了解模块化的好处,CommonJS 是什么,模块的三大分类,模块加载机制
- 熟练使用 npm 不同版本号的原理
模块化:按照固定的规则,把大文件拆分成独立且互相依赖的多个小模块。好处:代码复用性,代码可维护性,按需加载模块。
模块化规范:按照统一的导入导出语句,这样全部的模块接口就一致了。
07.模块化-模块的分类&require的使用¶
模块的分类:内置模块 fs;自定义模块;第三方模块 egg
加载模块使用 require
const fs = require('fs');
const cumtom = require('./custom.js');
const moment = require('moment');
使用 require 方法加载模块时,会执行被加载模块中的代码;
08.模块化-模块作用域和module对象¶
模块作用域:类似函数作用域,模块外部无法访问模块内置的变量和函数。
模块作用域的好处:避免全局变量污染的问题
09.模块化module.exports对象的使用¶
每一个模块内部,都有一个 module 对象,存储了和当前模块有关的属性和方法
Module = {
id: '',
path: '/test/code',
fileName: '/test/code/index.js',
exports: {}
};
// 还有其他属性和方法
重要的是 exports 对象,提供了对外的输出
10.模块化-exports对象¶
module.exports.name = 'hello';
module.exports.sayHi = function() {
console.log('hi');
}
const m = require('./hello.js');
console.log(m);
实际导出的结果,永远以 module.exports 指向的对象为准。
nodeJS 中,exports 和 module.exports 默认指向同一个对象。如果手动更改了指向,最后还是指向 module.exports 指向的对象。
exports === module.exports
11.模块化-exports和module.exports的使用误区¶
通常不要混合使用 exports 和 module.exports。直接使用 exports 即可。
通常不要更改 module.exports 的指向,以及 module 的其他属性方法等。
12.模块化-CommonJS模块化规范¶
commonJS 规定了模块的特性和各模块之间的互相依赖规范。
- 每个模块内部,module 变量表示当前模块
- module.exports 是对外的接口
- require 用于加载模块
13.包与npm-包的概念¶
包 === 第三方模块
nodeJS 内置模块是官方开发的,第三方模块是第三方的个人或者团队开发出来的,大部分是免费开源的。
为什么有第三方模块:因为有些内置模块使用不方便,那么就基于内置模块封装成包,可以提高开发效率。
NPM——node package manager 包管理工具,使用这个工具去安装管理包
14.包与npm-格式化时间的两种做法¶
通过格式化时间的案例,说明原生实现和 moment 实现两种方法
原生方案¶
- 新建格式化时间的方法
- 新建补零函数
- 自定义模块封装导出
- 调用格式化时间的函数
代码实现
function dateFormat(dateStr) {
const dt = new Date(dateStr);
const y = dt.getFullYear();
const m = padZero(dt.getMonth() + 1);
const d = padZero(dt.getDate());
const hh = padZero(dt.getHours());
const mm = padZero(dt.getMinutes());
const ss = padZero(dt.getSeconds());
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}
function padZero(n) {
return n > 9 ? n : `0${n}`;
}
module.exports = { dateFormat };
const TimeUtils = require('./time-utils');
const dt = new Date();
const newDt = TimeUtils.dateFormat(dt);
这种实现比较麻烦,而且需要自定义函数处理格式和月份加1
moment 方案¶
- 安装 moment,引入 mement
- 参照官网 API 格式化需要的时间
注意:HH 和 hh 是24小时和12小时,实际项目中要统一
const moment = require('moment');
const dt = moment().format('YYYY-MM-DD HH:mm:ss');
15.包与npm-使用npm的其它注意点¶
文件目录:安装包后,项目中 package-lock.json 和 node_modules 会多出文件。Package-lock.json 中记录了每一个包的下载信息和依赖树,不需要手动更改,安装时会自动更新。
包版本号说明:三位数字
- 第一个是大版本,表示和上一个大版本从底层上更新
- 第二个是功能版本,表示新加入或者修改某些主要功能
- 第三个是 bug 修复版本,或者添加小的功能等
实际发包时,后两位的区分没有那么明显。只要前面的版本提升了,后面的版本号需要归零。