Nodejs基本介绍
目标
- 掌握Node.js的基本概念;
- 了解Node.js在前端和后端领域中的作用
提问:前端要学什么编程语言?后端会用什么编程语言?(phy, python, java.....)
提问:可以用js语言实现后端的功能吗?
Node.js是什么
Node.js® 是一个基于 Chrome V8 引擎 的 JavaScript 运行时。
名词解释
-
chrome V8引擎:
-
chrome: chrome浏览器
-
引擎:用来解析和执行代码的工具。
汽车发动机引擎可以将燃油转成动力; JS解析引擎可以将代码转成最终的效果 -
V8:项目的代号
-
-
运行时:理解为一个容器,用来运行代码的环境;
示意图
大白话: nodejs提供了一个运行环境,我们在这个环境中可以运行js代码,这个环境是基于V8引擎来实现的。
Node.js可以做什么
Node.js 作为一个 JavaScript 的运行环境,仅仅提供了基础的功能和 API,而基于 Node.js程序员实现了很多强大的工具和框架。
具体来说:
- 后端API接口。基于Node.js环境 + Express框架,
- 桌面应用。基于Node.js环境 + Electron 框架
- 操作数据库。基于Node.js环境 + MySql包 读写和操作数据库
- 实用的命令行工具。基于Node.js环境,实现的 vuecli,webpack等
- etc...
总之,Node.js 是大前端时代的“大宝剑”,有了 Node.js 这个超级 buff 的加持,前端程序员的行业竞争力会越来越强!
Node.js为什么要学习
-
给学习前端框架,工具打下基础
-
更深入的模块化
-
了解服务器后端工作
-
增加职场竞争力
Node.js的学习内容
它只是一个环境,不是一门语言(不需要学习新语言),我们要学习:
- Node.js内置API模块(fs, path等....)
- 第三方API模块
下装安装Nodejs
目标
在官网上下载并安装Nodejs; 会检查本地Nodejs是否安装完成;
下载
版本说明:
- LTS: 长期稳定版(Long Term Support)。 项目开发建议使用长期稳定版
- Current: 最新尝鲜版 。最新版包含了一些新功能,如果想学习最新的功能,则可以使用该版本。最新版可能会有一些未知的bug。
下载
点击左侧的按钮(有LTS标识的那个),会立即下载,注意:不同系统选择对应的安装文件。
安装
- 找到你下载的安装包(不同的版本有不同的安装包)
-
双击安装文件开始安装
傻瓜式安装,一路
next即可
注意:
- 建议安装目录所使用
英文路径(不要安装在类似于 d:/软件/node)最好不要修改路径 选择默认 后期插件或其他会莫名其妙报bug - 安装完成之后, 它不会在桌面出现快捷图标
测试是否安装成功
打开终端,在终端的命令窗口中输入 node -v 命令,按下回车键。
如果在终端窗口中能够打印出 Node.js 的版本号,就证明 Node.js 已经安装成功,完全满足后续的学习需求。
什么是终端?
终端
(英文:Terminal)是专门为程序员设计的,通过输入命令来操作电脑的一种方式(装 X 神器)。
作为程序员,非常有必要学习一些常用的终端命令,来辅助我们更好的操作与使用计算机。
Windows 系统快速打开终端的三种方式:
-
cmd窗口(window+R, --->运行-->录入cmd,回车)
0. 在资源管理器的地址栏中,输入
cmd 后直接回车,即可打开终端
- 任意位置,shift+右键
Mac 电脑快速打开终端的方式:由于没有Mac 就不做演示啦
①使用快捷键 Command(⌘) + 空格键 打开搜索窗口
②在搜索窗口中输入 terminal 并回车,即可打开终端
在Node环境下运行js代码
我们没有接触node.js以前,js代码都是在浏览器中运行的,现在开始学习nodejs后,我们有了第二个可以运行js代码的环境。下面来学习如何去运行。
目标
掌握在NodeJS环境下运行js代码的步骤
步骤:
- 准备好要被执行的js文件
- 在命令行工具中写命令来运行这个文件
准备一个JS文件
请事先准备好一个js文件。例设这里的路径是:d:/src/index.js
具体内容如下:
// d:/src/index.js
var a = 1;
console.info(a + 2);
打开命令行工具,运行这个文件
格式
node 要执行的文件的路径
注意:node 的后面有一个空格
示例
例如:
node 01.js # 01.js就是当前目录下
node a/01.js # 01.js在目录a下面
小结
-
运行js代码的格式:
格式:
node 文件的位置 -
注意:
最好是在当前文件所在目录下来运行这个js文件
学习常用的命令行下的命令及按键
命令及键盘按键
一共有9个
(1)node 空格 某个js文件 // 调用 node 程序,运行某个js文件
(2)clear 或者 cls // 清空界面
(3)ls 或者 dir // 查看列表(list)
(4)cd 目录名 // 进入到目录中去
(5)cd .. // 返回上一级目录
(6)cd \ // 直接回到根目录
(7)Ctrl+C // 停止 Node 程序
(8)输入部分文件名后按下 Tab 键 // 补全文件名 或 目录名, 多次tab会进行切换
(9)↑ ↓ 上下箭头 // 切换历史输入
复制粘贴
在小黑窗中复制内容:选中内容,再点鼠标右键
把粘贴板中的内容复制到小黑窗: 点鼠标右键
课堂练习
- 下载安装nodejs
- 检查node的版本
- 学习常用的命令行下的命令及按键
Nodejs和浏览器端的区别
目标
了解NodeJs和浏览器端的区别
在浏览器端
javascript由三部分组成:ECMAScript + BOM + DOM
es6 ==> ECMAScript 6.0
在nodejs端
有ECMAScript + 内置模块(fs, http, path,.....)。在nodejs中是没有BOM、DOM、window,但使用ECMAScript是通用的
NodeJS中没有DOM,也没有BOM,也没有window对象。
ECMAScript
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,European Computer Manufacturers Association)通过ECMA-262组织的标准化的脚本程序设计语言。
ECMAScript是javascript语言的一个标准。它约定了:如何定义变量,函数,运算,数组,内置对象等等。
小结
相同点:
- 都是可以运行js代码的容器
- 都可以运行ECMAScript
不同点
- 各有不同的API: 在nodejs下 就不能写DOM, BOM,也不能用window对象了
- 运行代码的方式不一样
Nodejs中的模块分类
目标
了解nodejs中的模块分类
每个模块都是一个独立的文件。每个模块都可以完成特定的功能,我们需要时就去引入它们,并调用。
nodejs模块的分类
-
- 就是nodejs自带的模块,在安装完nodejs之后,就可以直接使用啦。
- 相当于学习js时使用的alert,confirm等函数。
-
第三方模块
- 其他程序员写好的模块。nodejs生态提供了一个专门的工具npm来管理第三方模块,后面我们会专门讲到。
- 相当于别人写好的函数或者库。例如JQuery库,artTemplate等。
-
自定义模块
- 程序员自己写的模块。
- 相当于我们在学习js时的自定义函数。
核心模块的基本使用
目标
了解核心模块的概念,掌握核心模块的基本使用方法
核心模块
核心模块就是 Node 内置的模块,安装完Nodejs之后,开箱即用
-
每个核心模块都有唯一的标识名称
-
核心模块有很多个,每个模块都有直接的作用,这里有文档。
-
使用步骤都是先导入,再使用
来进行获取。每一个核心模块基本上都是暴露了一个对象,里面包含一些方法供我们使用。一般在加载核心模块的时候,变量(或常量)的起名最好就和核心模块的标识名同名。
例如:const fs = require('fs')
const path = require('path') // 1. 导入模块
const str = path.join('a', 'b') // 2. 使用模块
console.log(str)
用require来导入模块
每个核心模块有自己的功能,想用哪个就导入哪个。
语法格式
const 模块的接收名称 = require('模块名字')
其中:
- 模块的接收名称可以自定义,只要是合法的变量名即可。例如:
const 123fs = require('fs') // 错误,不能以数字开头
const p = require('path') // 正确
- const 。可以使用var、let,但是建议使用const,因为我们不希望它被改变。名字不必大写成FS,一般也就叫fs这个名字。
使用模块
导入成功之后:
带着自己的目标,查官方手册。
fs模块
fs模块(fs是 FileSystem的简写)是Node.js用来进行文件操作的模块,它属于核心模块。你引入之后就可以直接使用了。
官方手册:nodejs.cn/api/fs.html api.nodejs.cn/
核心模块的使用步骤:
-
引入模块
// 引入模块 const fs = require('fs'); // 可以使用var、let,但是建议使用const,因为我们不希望它被改变。 // 名字不必大写成FS,一般也就叫fs这个名字。 -
调用api实现自己的要求
fs.apiName()
fs模块中操作文件(或者文件夹)的方法,大多都提供了两种选择:
- 同步版本的
- 异步版本的
小结
核心模块是指fs
fs-readFile-异步格式
目标
写代码去读出文件内容,并打印在屏幕上
格式
fs.readFile('文件路径'[,选项], function (err, data) {
if (err) {
console.log('有错误,错误内容是', errr)
} else {
console.log('读入文件正确,内容是', data)
}
});
说明:
-
参数1:文件路径。 相对路径和绝对路径均可。
-
参数2: 配置项,可不写。主要用来配置字符集。一般可设置为
utf8,如果不设置该参数,文件内容会Buffer形式返回。 -
参数3: 回调函数。这个回调函数在读完文件后自动被自动调用,并传入 err 和 data
-
如读取成功,回调函数中的两个参数分别是:
-
err: null
-
data: 文件内容。如果不设置参数2,则返回二进制数据。可以使用 toString() 方法将二进制数据
转为正常字符串
-
-
如读取失败,回调函数中的两个参数分别是:
- err: 错误对象
- data: undefined
-
示例1:读文本内容
const fs = require("fs")
fs.readFile('文件路径',(err, data) => {
if (err) throw err;
console.log(data);
});
上面的data将会是一个Buffer对象类似于数组,它的元素为16进制的两位数,它表示读出来的内容在计算机中的二进制格式。它有一个toString()方法,可以用来把内容以UTF-8的格式转成字符串。
示例2:读文本内容-指定编码格式
const fs = require("fs")
fs.readFile('文件路径', "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});
示例3:读入图片文件
const fs = require("fs")
fs.readFile('./img/1.jpg', (err, data) => {
if (err) throw err;
console.log(data);
});
并不是它所有的文件都应该转成字符串的
示例4:体会异步的效果
异步的
const fs = require("fs")
console.log(1)
fs.readFile('文件路径', "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});
console.log(2)
并不是它所有的文件都应该转成字符串的
练习
-
读文件试一试
- 不同类型的:.txt. , .js, .jpg, .avi(读一个很大电影)
- 不写utf8,写utf8
- 体会一下异步
fs-readFile-观察并处理错误
nodejs中的错误界面相比浏览器中的错误来说,并不友好。
如果读文件有错误
fs.readFile('./02.txt12112',function(err, data) {
// 如果读文件出错了(可能的原因:路径不对,文件不存在....)
// err的值就不是null
// if(出错) {
// 处理错误
// } else {
// 正常
// }
if(err){
// throw: 抛出
// throw 这个命令用来告诉node.js,这里有一个错误
// 停止后续代码的执行
console.log(err)
return
// throw err;
// 尽早返回
}
console.log('读出的内容是', data)
})
在node.js中遇到的错误之后,应该观察错误说明
fs-readFile-同步格式
格式
const fs = require("fs")
let rs = fs.readFileSync('文件路径',"utf8");
console.log(rs)
- api的名字后面有Sync(async是异步的,sync表示同步的)
- 不是通过回调函数来获取值,而是像一个普通的函数调用一样,直接获取返回值
捕获同步格式中的错误对象
如果读成功,则会获取读出来的数据,如果失败了,则会中断后续所有的代码执行。
console.log(1)
let res = fs.readFileSync('errorPath.js')
console.log(res)
console.log(2)
解决方案:用try. catch 结构
try {
const fs = require("fs")
let rs = fs.readFileSync('文件路径',"utf8");
console.log(rs)
} catch(err) {
console.log(err)
}
fs-writeFile-文件覆盖写入
覆盖写入 writeFile
功能:向指定文件中写入字符串, 如果没有该文件则尝试创建该文件。它是覆盖写入:会把文件中的内容全部删除,再填入新的内容。
格式:
fs.writeFile(pathName, content, option, (err)=>{});
// 参数1: 要写入的文件路径 --- 相对路径和绝对路径均可,推荐使用绝对路径
// 参数2: 要写入文件的内容
// 参数3: 配置项,设置写入的字符集,默认utf-8
// 参数4: 写入完成后触发的回调函数,有一个参数 --- err (错误对象)
示例1: 写入.txt文件
const fs = require('fs')
fs.writeFile('./a.txt', 'hello world! \n 换一行', err => {
if (err) {
console.info(err)
throw err
}
})
示例2: 写入json
稍微把问题提升一下,问: 如何把数据写入文件中?
const fs = require('fs')
const data = [{name: '小王', age: 20}]
fs.writeFile('./a.txt', data, err => {
if (err) {
console.info(err)
throw err
}
})
上面的写法会出错: data不是一个字符串或者是Buffer
正确做法是用JSON转一下。
const fs = require('fs')
const data = [{name: '小王', age: 20}]
fs.writeFile('./a.txt', JSON.stringify(data), err => {
if (err) {
console.info(err)
throw err
}
})
fs-appendFile-文件追加写入
功能
向指定文件中写入字符串(追加写入), 如果没有该文件则尝试创建该文件。
格式
fs.appendFile(pathName, content, option, callback);
// 参数1: 要写入的文件路径 --- 相对路径和绝对路径均可,推荐使用绝对路径
// 参数2: 要写入文件的字符串
// 参数3: 配置项,设置写入的字符集,默认utf-8
// 参数4: 写入完成后触发的回调函数,有一个参数 --- err (错误对象)
示例
const fs = require('fs')
fs.appendFile('./a.txt', '\n 为天地立命', err => {
if (err) {
console.info(err)
throw err
}
})
\n : 表示换行
路径问题-相对路径的隐患
在读取文件时,使用相对路径是容易出问题的。
下面我们来看会出什么问题。
素材准备
假设有如下两个文件,它们所处的目录及文件名如下所示:
|-day02
|------02code-nodejs
|--------------------03.fs.js
|--------------------03.fs.txt
03.fs.js代码的作用是读出03.fs.txt中的内容,并显示出来,它的代码是这样的:
// 03.fs.js
const fs = require('fs');
fs.readfilesync("./03.fs.txt",'utf8');
//注意这里对03.fs.txt的访问使用的是相对"fs.js" 本身的路径
由于03.fs.js和要读取的目标03.fs.txt是在同级目录下,所以可以写相对路径。
运行代码
想要运行03.fs.js这个文件有多种方式,根据当前处在的位置不同:
- A. 如果终端中的路径定位在
day02/02code-nodejs目录下,则通过node 03.fs.js可以顺序执行 - B. 如果终端中的路径定位在
day02目录下,则通过:node 02code-nodejs/03.fs.js能成功执行.js文件,但是却找不到文件路径了。
原因分析
我们在fs中读取文件时,由于使用的是相对路径,所以在读这个文件的时,nodejs会去:
运行命令的小黑窗的路径 + 代码中的相对路径 找它。
所以上述代码中:
- A方案在运行时,找到的文件是
day02/02code-nodejs/03.fs.txt,它可以找到文件 - B方案在运行时,找到的文件是
day02/03.fs.txt,它就找到不文件了
解决方法
就是在操作文件时,使用绝对路径来定位文件。
D:/node-learn/02-代码/day01/js/info.txt
小结
在读写文件时,尽量不要采用相对路径,它容易出问题。
路径问题-获取绝对路径
目标
掌握 __dirname 和 __filename的用法,并在操作文件路径时正确使用
__dirname,__filename
__filename 和 __dirname 是 Node.js 内置的全局变量
-
特点是:不用声明就能直接使用
-
全局变量的含义是:
- 变量:它们的值是变化的。在不同的文件中值就不同。
- 全局:在任意地方都可以直接使用。
-
其中:
__filename 表示当前文件的完整路径(包含文件名)
__dirname 表示当前文件的完整存放目录(不包含文件名)
测试使用,在任意代码的任意位置
console.log(__dirname)
console.log(__filename)
在文件操作时,使用绝对路径
只需要在读入文件时,在路径前面拼接上:
// 拼接html5.jpg的绝对路径
// 1) 找到当前文件夹的绝对路径
console.log(__dirname)
const fs = require('fs')
// 2) 加上 html5.jpg
const filePath = __dirname + '\html5.jpg'
// 走一步,看一步
console.log(filePath)
// 3)读入文件
fs.readFile(filePath,function(err, data) {
if(err) {
console.log(err)
return
}
console.log(data)
})
path模块
作用
path也是node中的核心模块,作用是用来处理路径问题:拼接,分析,取后缀名等等。
使用步骤
- 引入模块
const path = require('path')
- 使用模块
常用的api
- path.basename():此方法返回
path的最后一部分。一般可用来获取路径中的文件名。 - path.join(): 路径拼接
- path.extname(): 获取后缀名
示例
path.basename('/foo/bar/baz/asdf/quux.html');// 返回: 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', '.html');// 返回: 'quux'
path.dirname('/foo/bar/baz/asdf/quux');// 返回: '/foo/bar/baz/asdf'
path.extname('index.html');// 返回: '.html'
注意:不考虑其中地址是否真的存在,只是单纯调用方法,获取结果。
路径问题-使用path模块解决文件读写中的路径拼写
// 拼接html5.jpg的绝对路径
// 1) 找到当前文件夹的绝对路径
console.log(__dirname)
// 2) 加上 html5.jpg
const fs = require('fs')
const path = require('path')
const filePath = path.join(__dirname, 'html5.jpg')
// const filePath = __dirname + '\html5.jpg'
// 走一步,看一步
console.log(filePath)
fs.readFile(filePath,function(err, data) {
if(err) {
console.log(err)
return
}
console.log(data)
})
附:path模块常用方法列表
| 方法 | 作用 |
|---|---|
| path.basename(path[, ext]) | 获取返回 path 的最后一部分(文件名) |
| path.dirname(path) | 返回目录名 |
| path.extname(path) | 返回路径中文件的扩展名(包含.) |
| path.format(pathObject) | 将一个对象格式化为一个路径字符串 |
| path.join([...paths]) | 拼接路径 |
| path.parse(path) | 把路径字符串解析成对象的格式 |
| path.resolve([...paths]) | 基于当前工作目录拼接路径 |
附:fs模块中的常用方法
| API | 作用 | 备注 |
|---|---|---|
| fs.access(path, callback) | 判断路径是否存在 | |
| fs.appendFile(file, data, callback) | 向文件中追加内容 | |
| fs.copyFile(src, callback) | 复制文件 | |
| fs.mkdir(path, callback) | 创建目录 | |
| fs.readDir(path, callback) | 读取目录列表 | |
| fs.rename(oldPath, newPath, callback) | 重命名文件/目录 | |
| fs.rmdir(path, callback) | 删除目录 | 只能删除空目录 |
| fs.stat(path, callback) | 获取文件/目录信息 | |
| fs.unlink(path, callback) | 删除文件 | |
| fs.watch(filename[, options][, listener]) | 监视文件/目录 | |
| fs.watchFile(filename[, options], listener) | 监视文件 | |
| fs.existsSync(absolutePath) | 判断路径是否存在 |
\