Skip to content

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 设置返回值。

实现思路(先一定把思路理清楚)——这个教程最大的收获是如何分析问题

  1. 获取请求的URL
  2. 设置默认的相应内容是404
  3. 设置请求首页内容
  4. 设置关于页面内容
  5. 处理中文乱码
  6. 返回客户端
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 规定了模块的特性和各模块之间的互相依赖规范。

  1. 每个模块内部,module 变量表示当前模块
  2. module.exports 是对外的接口
  3. 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 修复版本,或者添加小的功能等

实际发包时,后两位的区分没有那么明显。只要前面的版本提升了,后面的版本号需要归零。


Last update: November 9, 2024