Node.js入门(一):常见的内置模块

前言

在学Node.js之前需要掌握以下技能的基础知识:

  • ES6常用语法
  • http协议基础
  • JavaSacript的运行机制
  • 线程和进程的概念

假定你已经掌握了相关的基础知识了,那么我们今天开始正式来学习Node.js吧!

环境准备

  1. Node.js官网 下载安装包,下稳定版本即可。
  2. 傻瓜式安装,下一步下一步即可,默认是在C盘
  3. 新版本不需要在手动配置环境变量了,而且会默认给你装好npm包管理器下载完成后,打开cmd输入以下命令测试:
node -v
npm -v

如果出现一个版本号说明安装成功啦!
在这里插入图片描述

  1. 有时候npm很慢,那么需要国内的镜像来替代它,首选淘宝镜像,据说10分钟同步更新,速度很快!
npm install -g cnpm --registry=https://registry.npm.taobao.org
  1. 测试cnpm
cnpm -v

在这里插入图片描述
成功啦!下面我们开启Node.js的学习之旅吧!

HTTP

此时此刻,我异常激动,终于学习到了服务器端啦。和其他web服务器一样,Node.js有HTTP服务,文件的读写等操作,而且我们不必对TCPHTTP协议本身进行操作,Node.js直接把它们内置成了自己模块:httpfs等。和ES6的模块化不一样,Node.js有着自己的模块化,我们一开始就是从内置模块学习的,模块化本身我们一开始先不学习,先学会用它的内置模块,然后过一段时间的我们就有自己的体会啦,到时候我再来自己总结。

我们先来学习一下这个模块中的两个很重要的对象:requestresponse

request对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息

response对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器

  1. 引入http模块
const http = require('http');
  1. 创建一个http服务,requestresponse(可以简写)作为回调函数的参数,表示当浏览器访问这个服务器的时候执行回调函数
const server = http.createServer((req, res) => {
	//1.对http请求的操作,比如解析url
	...
	// 2.对http请求的响应,比如返回状态码,响应头,响应体
	...
});
  1. 监听端口,以8080端口为例
server.listen(8080)

对这个过程简单了解后,下面我们可以来试试:

// 引入http模块
const http = require('http');

// 创建一个端口号为8887的http服务
http.createServer(function (request, response) {
  console.log('request come', request.url)

  // 允许任意url跨域,设置响应头
  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*',
    'Content-Type': 'text/html'
  });
  //  对任意请求返回一个html
  response.end('<h1>hello world</h1>');
}).listen(8887);

console.log('server listening on 8887');

启动这个服务,然后我们在浏览器输入

http://localhost:8887/

浏览器显示了:
在这里插入图片描述
同时我们看控制台也打印了请求的url信息:
在这里插入图片描述
我们也可以打开浏览器开发者工具查看Network:
在这里插入图片描述
响应头里面就是我们刚刚设置的字段,当然还有默认的字段。

响应体放回了一个html让浏览器自己解析:
在这里插入图片描述

到目前为止我们已经算是对http模块有了一个基本的了解了,但是这种数据返回给浏览器的类型很局限,那如果是图片、音频和视频文件这种二进制的数据该怎么发呢,那么此时此刻又需要另外一个模块了:fs模块,并且配合http模块一起使用。

fs

fs模块是一个读取文件的模块,那么读取文件的操作又分为同步的操作和异步的操作,而这个模块都提供了相关的方法,我们先以本地文件的读写作为切入点。

在此之前你需要明白同步和异步的概念,这个非常重要,我简单来说一说。

同步的操作是必须等待一个操作完成才能继续执行下面的代码,以读文件为例,必须读完这个文件之后,返回了一个结果才能往后继续操作。

异步的操作是不用等待的,知识把这个将来要出现的结果放在了回调函数之中,继续执行后面的代码,等异步出现结果了再去拿到这个结果进行操作。

有了这个概念后我们开始我们的文件操作吧!以异步操作为例:(同步的方法就不用了)

  1. 引入fs模块(和上面的http模块一样)
const fs = require('fs');
  1. 使用读写文件的方法
// 1.读文件 有三个参数:路径、文件编码、回调函数(有两个参数,err和data)
fs.readFile(path, encoding, callback)

// 2.写文件 有三个参数:路径、数据、回调
fs.writeFile(path,data,callback)

实操一波:
我们先写入一个文件test.txt,然后再读取这个文件

const fs = require('fs');

fs.writeFile('./test.txt', 'hello', err => {
  if (err) {
    console.log('写入失败!');
  } else {
    console.log('test文件写入成功!');
  }
});

运行后发现成功了!
在这里插入图片描述
而且项目中多了一个文件
在这里插入图片描述
然后我们对这个文件进行读取操作:

const fs = require('fs');

fs.readFile('./test.txt', 'utf-8', (err, data) => {
  if (!err) {
    console.log(`文件成功读取,文件内容是:${data}`);
  } else {
    console.log('读取文件错误!');
  }
});

控制台输出了hello,也就是说成功读到了数据。

在这里需要注意一个点就是:当读取二进制文件时,不传入文件编码时,回调函数的data参数将返回一个Buffer对象。在Node.js中,Buffer对象就是一个包含零个或任意个字节的数组(注意和Array不同)。

上面使用模板字符串将data拼到了字符串里面,也就是说将Buffer对象转化了字符串显示了,如果单独显示就是一个Buffer对象,直接console,我们看看:
在这里插入图片描述
如果要显示我们能看得懂的数据,有两种方式:

  • 第一在readFile这个方法里面加上第二个参数,即编码格式
  • 调用toString方法显式转化为字符串

当然如果需要转化成Buffer需要使用Buffer对象的from方法。

下面补充一个stat方法,这个方法是获取文件大小,创建时间等信息的。

const fs = require('fs');

fs.stat('test.txt', (err, stat) => {
  if (err) {
    console.log(err);
  } else {
    // 是否是文件:
    console.log('isFile: ' + stat.isFile());
    // 是否是目录:
    console.log('isDirectory: ' + stat.isDirectory());
    if (stat.isFile()) {
      // 文件大小:
      console.log('size: ' + stat.size);
      // 创建时间, Date对象:
      console.log('birth time: ' + stat.birthtime);
      // 修改时间, Date对象:
      console.log('modified time: ' + stat.mtime);
    }
  }
});

控制台输出:
在这里插入图片描述
但是,如果要读取一个很大的文件的时候,上面的那种操作很麻烦,效率也不高,那么接下来需要介绍一个很神奇的数据结构:流(stream

stream

流是一种抽象的数据结构。流的特点是数据是有序的,而且必须依次读取,或者依次写入,不能像Array那样随机定位。

stream十分抽象,但对于文件的读写十分有用,它也是一个对象,并且都是EventEmitter(以后会将到) 的实例,常见的事件有:

  • data - 当有数据可读时触发。

  • end - 没有更多的数据可读时触发。

  • error - 在接收和写入过程中发生错误时触发。

  • finish - 所有数据已被写入到底层系统时触发。

下面来看看使用流来进行文件读写操作:

和上面一样,先写入一个文件先

const fs = require('fs');

// 创建一个可以写入的流,写入到文件 test.txt 中,写入的数据全部以'utf-8'编码
let ws = fs.createWriteStream('./test.txt', 'utf-8');
// 源源不断写入数据...
ws.write('start\n');
ws.write('hello node!\n');
ws.write('end');
// 标记文件末尾
ws.end();
//处理事件
ws.on('finish', () => {
  console.log('文件写入成功!');
});
ws.on('error', ()=> {
  console.log('文件写入失败');
});

控制台显示
在这里插入图片描述
这说明,数据已经全部写入了文件,并且触发了finish事件。

同样我们读取这个文件也有两个事件:

const fs = require('fs');

// 创建一个读取流,以'utf-8'编码
let rs = fs.createReadStream('./test.txt', 'utf-8');

// 事件监听

// 有数据时触发
rs.on('data', chunk => {
  console.log('start read');
  console.log(chunk);
});

// 读完触发
rs.on('end', () => {
  console.log('end read ');
});

// 出错触发
rs.on('error', err => {
  console.log(err.stack);
});

控制台输出:

在这里插入图片描述
除此之外还有一个很神奇的东西:管道流

管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。

有点像两根自来水管接在一起了,前面一根的水流到了后面那一根,流着同样的水。也就是一个文件里面数据流到了另外一个文件,其实有点像复制。

我们来瞧瞧:

const fs = require('fs');

// 创建一个读取流
let rs = fs.createReadStream('./test.txt');

// 创建一个可以写入的流,写入到文件 test.txt 中
let ws = fs.createWriteStream('./test2.txt');

//将读到的文件数据写到另一个文件
rs.pipe(ws);

此时此刻我们看多了一个test2.txt文件,内容和test.txt一模一样
在这里插入图片描述
感觉就是复制了一份一样是不是,很神奇很好玩。

常用的内置模块暂告一段落啦,以后遇到别的我会继续来补充的。

参考

【1】廖雪峰的官方网站
【2】菜鸟教程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值