关于nodejs的基础知识

1.什么是NodeJS

简单的说 Node.js 就是运行在服务端的 JavaScript。

Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。

Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

2.nodejs基础知识

global模块-全局变量

Node.js 中的全局对象是 global, 类似于浏览器中的window

常用的global属性:

console: 用于打印日志
setTimeout/clearTimeout: 设置清除延时器
setInterval/clearInterval: 设置清除定时器

__dirname: 当前文件的路径,不包括文件名
__filename: 获取当前文件的路径,包括文件名

//与模块化相关的,模块化的时候会用到
require
exports
module

注意:

  • 除了global模块中的内容可以直接使用,其他模块都是需要加载的。
  • 其他模块不是全局的,不能直接使用。因此需要导入才能使用。

fs模块

fileSystem-- 文件系统,提供了一系列操作文件的API接口,可以方便我读写文件

读取文件

语法:fs.readFile(path[, options], callback)

方式一:不传编码参数

//参数1: 文件的名字
//参数2: 读取文件的回调函数
//参数1:错误对象,如果读取失败,err会包含错误信息,如果读取成功,err是null
//参数2:读取成功后的数据(是一个Buffer对象)
fs.readFile("data.txt", function(err, data){
  console.log(err);
  console.log(data);
// 可以通过data.toString() 把二进制数据转成文本,当然前提是读取的文件本来就是文本,如果是图片获取的二进制就无法转换成文本
});

方式二:传编码参数

//参数1: 文件的路径
//参数2: 编码,如果设置了,返回一个字符串,如果没有设置,会返回一个buffer对象
//参数3: 回调函数
fs.readFile("data.txt", "utf8",function(err, data){
  console.log(err);
  console.log(data);
});

写文件

语法:fs.writeFile(file, data[, options], callback)

//参数1:写入的文件名(如果文件不存在,会自动创建)
//参数2:写入的文件内容(注意:写入的内容会覆盖以前的内容)
//参数3:写文件后的回调函数
fs.writeFile("2.txt", "hello world, 我是一个中国人", function(err){
  if(err) {
    return console.log("写入文件失败", err);
  }
  console.log("写入文件成功");
});

注意:
写文件时,会把文件中原本的内容替换

追加文件

语法:fs.appendFile(path, data[, options], callback)

//参数1:追加的文件名(如果文件不存在,会自动创建)
//参数2:追加的文件内容(注意:写入的内容会覆盖以前的内容)
//参数3:追加文件后的回调函数
fs.appendFile("2.txt", "我是追加的内容", function(err){
  if(err) {
    return console.log("追加文件内容失败");
  }
  console.log("追加文件内容成功");
})

文件同步与异步的说明

fs中所有的文件操作,都提供了异步和同步两种方式	
1.异步方式:不会阻塞代码的执行
2.同步方式:会阻塞代码的执行

stream

stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构。

什么是流?流是一种抽象的数据结构。想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地到达另一个地方(比如洗手池)。我们也可以把数据看成是数据流,比如你敲键盘的时候,就可以把每个字符依次连起来,看成字符流。这个流是从键盘输入到应用程序,实际上它还对应着一个名字:标准输入流(stdin)。

如果应用程序把字符一个一个输出到显示器上,这也可以看成是一个流,这个流也有名字:标准输出流(stdout)。流的特点是数据是有序的,而且必须依次读取,或者依次写入,不能像Array那样随机定位。

有些流用来读取数据,比如从文件读取数据时,可以打开一个文件流,然后从文件流中不断地读取数据。有些流用来写入数据,比如向文件写入数据时,只需要把数据不断地往文件流中写进去就可以了。

在Node.js中,流也是一个对象,我们只需要响应流的事件就可以了:data事件表示流的数据已经可以读取了,end事件表示这个流已经到末尾了,没有数据可以读取了,error事件表示出错了。

举例:
'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
    console.log('DATA:')
    console.log(chunk);
});

rs.on('end', function () {
    console.log('END');
});

rs.on('error', function (err) {
    console.log('ERROR: ' + err);
});

要注意,data事件可能会有多次,每次传递的chunk是流的一部分数据。

要以流的形式写入文件,只需要不断调用write()方法,最后以end()结束:

'use strict';

var fs = require('fs');

var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();

所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable。

pipe

就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来。一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe。

在Node.js中,Readable流有一个pipe()方法,就是用来干这件事的。

让我们用pipe()把一个文件流和另一个文件流串起来,这样源文件的所有数据就自动写入到目标文件里了,所以,这实际上是一个复制文件的程序:

'use strict';

var fs = require('fs');

var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');

rs.pipe(ws);

默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流。如果我们不希望自动关闭Writable流,需要传入参数:

readable.pipe(writable, { end: false });

path模块

在读写文件的时候,文件路径可以写相对路径或者绝对路径

//data.txt是相对路径,读取当前目录下的data.txt, 相对路径相对的是指向node命令的路径
//如果node命令不是在当前目录下执行就会报错, 在当前执行node命令的目录下查找data.txt,找不到
fs.readFile("data.txt", "utf8", function(err, data) {
  if(err) {
    console.log("读取文件失败", err);
  }

  console.log(data);
});

  • 相对路径:相对于执行node命令的路径
  • 绝对路径:__dirname: 当前文件的目录,__filename: 当前文件的目录,包含文件名

path模块的常用方法

关于路径,在linux系统中,路径分隔符使用的是/,但是在windows系统中,路径使用的\

path.join();//拼接路径

//windows系统下
> path.join("abc","def","gg", "index.html")
"abc\def\gg\a.html"

//linux系统下
> path.join("abc","def","gg", "index.html")
'abc/def/gg/index.html'

http模块

创建服务器步骤:

// 移入http模块
const http = require('http')
// 调用创建http 服务器的方法
const server = http.createServe()
// 给服务器注册request事件监听,每次浏览器像服务器发送请求的时候都会被监听到
server.on('request', function(request, response){
    // request 浏览器请求的数据,包括请求方式method 请求的地址 url等
    // response 浏览器的响应,可以设置响应头、响应体、响应状态码
    const method = request.method
    const url = request.url
    
    // 设置响应的状态码
    response.StatusCode = 404
    // 设置响应的头
    response.setHeader('Content-Type', 'text/html');
    // 设置响应体内容,write可以调用多次
    response.write('hello world!')
    // 响应结束
    response.end()
    
    // 如果在end(content),这样的写法相当于是让write和end的合写
    response.end('hello world!')
})
// 给服务器设置监听,相当于启动服务器
server.listen(8888,function(){
    console.log('服务器启动成功')
})

// 简写方式

http.createServer((req,res) => {
    ....
}).listen(8888,() => {
    ....
})

  • 给服务器注册request事件,只要服务器接收到了客户端的请求,就会触发request事件
  • request事件有两个参数,request表示请求对象,可以获取所有与请求相关的信息,response是响应对象,可以获取所有与响应相关的信息。
  • 服务器监听的端口范围为:1-65535之间,推荐使用3000以上的端口,因为3000以下的端口一般留给系统使用

3.模块化(module)

基本概念:在nodejs中,应用由模块组成,nodejs中采用commonJS模块规范。

  • 一个js文件就是一个模块
  • 每个模块都是一个独立的作用域,在这个而文件中定义的变量、函数、对象都是私有的,对其他文件不可见。

node中模块分类

  • 核心模块:由 node 本身提供,不需要单独安装(npm),可直接引入使用
  • 第三方模块:由社区或个人提供,需要通过npm安装后使用
  • 自定义模块:由我们自己创建,比如:tool.js 、 user.js

核心模块

  • fs:文件操作模块
  • http:网络操作模块
  • path:路径操作模块
  • 基本使用:1 先引入 2 再使用

第三方模块

  • 第三方模块是由 社区或个人 提供的
  • 比如:mime模块/art-template/jquery…
  • 基本使用:1 先通过npm下载 2 再引入 3 最后使用

用户自定义模块

  • 由开发人员创建的模块(JS文件)
  • 基本使用:1 创建模块 2 引入模块
  • 注意:自定义模块的路径必须以./获取…/开头

模块导入

/* 
  nodejs中模块分为3大类
    1. nodejs本身提供的核心模块   fs http path url querystring
      核心模块不需要安装,直接导入即可。
      核心模块的加载语法: const fs = require('fs')
    
    2. 第三方模块  mime art-template
      第三方模块: 必须先安装(npm install XXX)  才能导入
      第三方模块的加载语法: npm install XXX   const mime = require('mime')
    
    3. 自定义的模块 一个js文件 
      不需要安装  只需要自己创建一个js文件
      自定义模块的加载语法:  require('模块的路径')  模块不能是名字,必须是路径  ./ ../ .js后缀是可以省略

  require加载规则(以mime模块为例)
  1. 判断是否是路径, 如果是  就是自定义模块
  2. 如果是名字 判断是否是核心模块
  3. 如果是第三方模块  在当前目录找node_modules
  4. 在node_modules中查找mime文件夹
  5. 查找是否有package.json, 查看是否main属性
  6. 判断是否有main, 如果没有,默认查找index.js  index.json index.node
  7. 如果没有
  8. 如果找不到,就去上一层目录,一直找到根目录
  9, 如果还没有,就说明模块不存在
*/

模块导出

/* 
  1. 模块中定义的变量和函数都是私有的
  2. 任意的一个模块中, 都有自带一个属性 module (全局属性) module代表的就是当前的这个模块。
  3. module中有一个属性  exports ,这个exports属性是一个对象,代表的就是当前模块的导出 module.exports当前模块唯一能够被外界访问到的

*/
//通过module.exports对外导出一些值
module.exports = 值  只能导出一个值
module.exports = {}  可以把所有要导出的内容都放到一个新的对象中
module.export.xxx = 值
/* 
  在任意的模块中 module.exports表示该模块的导出
  为了我们方便导出, 每个模块中还提供了 exports  
  exports 初始状态下,和module.exports指向了同一个对象。

  注意点: 如果通过exports的方式来导出内容,只能给对象增加属性 不能替换这个对象
*/
// 我们真正到处的对象是module.exports指向的对象
exports = {} // 这样只是改了exports的指向,而module.exports的指向没有改变,所以这样是不对的
// 以下这种是允许的
exports.xxx = '值'

猜你喜欢

转载自blog.csdn.net/weixin_47150940/article/details/107843305