一、Node简介
1.1 Node是什么
Node.js®是基于 Chrome的V8 JavaScript 引擎构建的JavaScript运行环境、运行时(runtime)。
Node.js不是新语言,也不是一个框架或者一个库,而是一个软件。2009出现的。
Node.js是一个 JavaScript 运行环境 ,说白了,就是用来运行js的。
中文官网:https://nodejs.org/zh-cn/
1.2. Node能做什么
Node 打破了过去 JavaScript 只能在浏览器中运行的局面。前后端编程环境统一,大大降低了前后端语言切换的代价。
- Node.js 适合开发服务器端的中间层(BFF)
- Node.js 适合用于开发前端方向的各种工具
以下是Node可以实现的工作:(仅作了解)
- Web 服务器
- 命令行工具
- 网络爬虫
- 桌面应用程序开发(Electron)
- app
- 嵌入式
- 游戏
- ......
1.3. 安装Node
中文官网:https://nodejs.org/zh-cn/
安装后,可打开终端如cmd,输入node -v 查看是否安装成功
二、Node.js 相关工具
2.1 nvm
我们知道,NodeJS有太多的版本了,切记,并不是新版本一出现,旧的版本就不去用了。
在不同的项目开发过程中,可能需要我们在电脑中同时存在多个不同版本的Node。
这时候就需要一个软件,来更好地管理这些不同版本地Node存在我们地电脑中,Nvm就是这样一个软件。
nvm (node.js version manager 的简写)翻译过来 nodejs 版本管理器。
2.1.1 安装Nvm
nvm下载链接 https://github.com/coreybutler/nvm-windows/releases
注意:如果电脑之前安装过nodejs,请先卸载nodejs后再进行安装。
检测nvm是不是安装成功了:
成功安装后,新开一个 cmd 窗口,输入 nvm -v
如果有信息,代表安装成功!
配置nvm:
复制下面两句话到nvm的安装目录的settings.txt的最后。
(目的是加快后面下载nodejs的速度)
node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/
2.1.2 nvm命令
- nvm version: 查看 nvm 的版本
- nvm list: 查看当前安装的 Node.js 所有版本 (常用)
- nvm install 版本号 [架构]: 安装指定版本的 Node.js (常用)
- nvm uninstall 版本号: 卸载指定版本的 Node.js
- nvm use 版本号: 选择指定版本的 Node.js (常用)
# 安装指定版本
nvm install 10.15.0
# 安装最新版本
nvm install latest
# 使用安装的这个版本10.15.0
nvm use 10.15.0
# 查看node版本
node -v
2.2 npm
npm
全称为 Node Package Manager
,是一个基于 Node.js
的包管理器,也是整个 Node.js
社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。
npm
全称为 Node Package Manager
,是一个基于 Node.js
的包管理器,也是整个 Node.js
社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。
- nodejs = ECMAScript + 核心模块
- 自己遵循 commonjs 规范写出模块,如果写的是功能模块(日期处理datejs,数字处理numberjs)。如果可以把这些模块分享出来,以后谁要进行相关功能开发的时候,直接拿开发好的模块使用即可,没必要自己在开发。在互联网有一个网站专门收集这样的工具包。https://www.npmjs.cn/。
- 如果我们要使用这个网站里面的包,则我们需要使用一个功能,叫做 npm。
npm可以用来:
- 允许用户获取第三方包并使用
- 允许用户将自己编写的包或命令行程序进行发布分享
2.2.1 npm安装
npm
不需要单独安装。在安装 Node
的时候,会连带一起安装npm
。
执行下面的命令可以用来查看本地安装的 npm 的版本号。
npm -v
如果想升级 npm ,可以这样
npm install npm --global(-g)
2.2.2 npm常用命令
- npm help 查看所有命令
npm help xxx 查看某条命令的详细帮助 - npm install (i) xxx 本地安装
npm install (i) xxx -g 全局安装 - npm list (ls) -g 查看所有全局安装的模块信息,list 可以简写为 ls
npm list (ls) xxx 查看某个安装的模块信息 - npm uninstall (uni) xxx 卸载模块
- npm update xxx 更新模块
- npm search xxx 搜索模块
- npm init 创建模块
- npm update <package> 可以把当前目录下
node_modules
子目录里边的对应模块更新至最新版本
npm update <package> -g 全局更新 - npm root -g 查看全局包安装位置
2.2.3 package.json和包的安装
# package.json初始化
npm init -y
# 安装包到生产环境(用户需要安装的),默认就是这个
npm install jquery --save(-S)
# 安装包到开发环境(用户可以不安装的)
npm install lodash --save-dev(-D)
# 查看包的所有版本
npm view jquery versions
# 安装包的指定版本
npm install jquery@2.2.2
# 卸载包
npm uninstall jquery
# 查看所有本地包的最新情况
npm outdated
# ~2.0.0表示patch, ^2.0.0表示minor * 表示xx最新版本
# 更新包
npm update
# 清除缓存,--force 是强制执行
npm cache clean --force
# 查看全局包安装位置
npm root -g
2.2.4 package.json
{
"name": "liwker-test", // 包名
"version": "1.0.1", // 版本号
"description": "", // 描述
"main": "index.js", // 入口文件
"scripts": { // 脚本
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Liwker",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.21"
}
}
2.2.5 npm 包版本符号
- ^ : 锁定major,第一个数
- ~ : 锁定minor,第二个数
- 空 : 锁定patch,第三个数(偶数为稳定,奇数为不稳定)
- *: 最新版本
"dependencies": {
"jquery": "^3.6.0"
}
2.2.6 上传自己的包
-
编写模块,保存为 index.js
exports.sayHello = function(){ return 'Hello World'; }
-
注册npm仓库账号(https://www.npmjs.com/)
npm adduser // 不是第一次登录 npm login
-
上传包
npm pubish
可以失败的原因:
-
403 Forbidden
一般是源的问题,淘宝源是不能登录的# 查看npm源 npm config get registry # 切换npm源方法一 npm config set registry http://registry.npmjs.org # 切换npm源方法二,需要安装nrm nrm use npm
-
Err 400
我就踩了这个坑
一是在注册账号后需要邮箱的验证
二是package.json中的name值也就是包的名字必须是全网唯一的三是包的名字不能有大写字母
上传好了后,可以在https://www.npmjs.com/搜到自己的包
就可以 npm install 自己的包
-
卸载包
# 查看当前项目引用了哪些包 : npm ls # 卸载包: npm unpublish --force
2.2.7 npm脚本
Node 开发离不开 npm,而脚本功能是 npm 最强大、最常用的功能之一。
1 什么是 npm 脚本?
npm 允许在 package.json 文件里面,使用 scripts 字段定义脚本命令。
{
// ...
"scripts": {
"build": "node build.js"
}
}
2 执行顺序
如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。
"scripts": {
"script1": "node script1.js",
"script2": "node script2.js"
}
如果是并行执行(即同时的并行执行),可以使用 &
符号。
npm run script1 & npm run script2
如果是继发(串行)执行(即只有前一个任务成功,才执行下一个任务),可以使用 &&
符号。
npm run script1 && npm run script2
多脚也可以写在json里
// 并行执行
"scripts": {
"start": "node script1.js & node script2.js"
}
// 串行执行
"scripts": {
"start": "node script1.js && node script2.js"
}
3 简写形式
常用的 npm 脚本简写形式。
npm start 是 npm run start
npm test 是 npm run test
4 变量
npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
首先,通过 npm_package_
前缀,npm 脚本可以拿到 package.json 里面的字段。比如,下面是一个 package.json。
注意:一定要在 npm 脚本中运行(如:npm run view)才可以,直接在命令行中运行JS(如:node view.js)是拿不到值的
{
"name": "foo",
"version": "1.2.5",
"scripts": {
"view": "node view.js"
}
}
那么,变量 npm_package_name 返回 foo,变量 npm_package_version 返回 1.2.5。
// view.js
console.log(process.env.npm_package_name); // foo
console.log(process.env.npm_package_version); // 1.2.5
上面代码中,我们通过环境变量 process.env 对象,拿到 package.json 的字段值。如果是 Bash 脚本,可以用$npm_package_name 和 $npm_package_version 取到这两个值。
2.2.8 npm 安装 git 上发布的包
# 这样适合安装公司内部的git服务器上的项目
npm install git+https://git@github.com:***.git
# 或者以ssh的方式
npm install git+ssh://git@github.com:***.git
2.2.9 cross-env 使用
- cross-envs 是什么
运行跨平台设置和使用环境变量的脚本
- 出现原因
当您使用 NODE_ENV=production, 来设置环境变量时,大多数 Windows 命令提示将会阻塞(报错)。(异常是Windows上的Bash,它使用本机Bash。)换言之,Windows 不支持 NODE_ENV=production 的设置方式。
- 解决
cross-env 使得您可以使用单个命令,而不必担心为平台正确设置或使用环境变量。这个迷你的包(cross-env)能够提供一个设置环境变量的 scripts,让你能够以 Unix 方式设置环境变量,然后在 Windows 上也能兼容运行。
- 安装
npm install cross-env -D
- 使用
{
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}
}
NODE_ENV环境变量将由 cross-env 设置 打印 process.env.NODE_ENV === 'production'
2.3. nrm
NRM(npm registry manager) npm源管理
2.3.1 手工切换源
1 查看当前源
npm config get registry
2 切换淘宝源
npm config set registry https://registry.npm.taobao.org
2.3.2 NRM 管理源
NRM (npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。
1 安装 nrm
在命令行执行命令,npm install -g nrm
,全局安装nrm。
2 使用 nrm
执行命令 nrm ls
查看可选的源。 其中,带*的是当前使用的源,上面的输出表明当前源是官方源。
如果安装成功,执行不起,显示:path.js:39 throw new ERR_INVALID_ARG_TYPE(‘path‘, ‘string‘, path)
解决问题:
1、运行,npm ls命令,找到npm的安装路径。
2、在资源管理器中,找到nrm的安装目录,一般是:C:\Users\Administrator\AppData\Roaming\npm\node_modules\nrm
3、在目录下找到cli.js文件。
4、用文本编辑器打开它。修改里面的一行代码:
原来代码是:const NRMRC = path.join(process.env.HOME, '.nrmrc');
修改为:const NRMRC = path.join(process.env.USERPROFILE, '.nrmrc');
5、重新运行,nrm ls成功。
3 切换 nrm
如果要切换到taobao源,执行命令 nrm use taobao
4 测试速度
你还可以通过 nrm test
测试相应源的响应时间。
nrm test
2.4 npx
npx: npm package extention
npm 从5.2版开始,增加了 npx 命令。它有很多用处,本文介绍该命令的主要使用场景。
Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下。
npm install -g npx
2.4.1 调用项目安装的模块
npx 想要解决的主要问题,就是调用项目内部安装的模块。比如,项目内部安装了Mocha。
npm install -D mocha
一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面,如果想在命令行下调用,必须像下面这样。
# 项目的根目录下执行
node-modules/.bin/mocha --version
npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。
npx mocha --version
npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。
# 等同于 ls
npx ls
注意,Bash 内置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。
2.4.2 --no-install 参数和 --ignore-existing 参数
如果想让 npx 强制使用本地模块,不下载远程模块,可以使用--no-install
参数。如果本地不存在该模块,就会报错。
npx --no-install http-server
反过来,如果忽略本地的同名模块,强制安装使用远程模块,可以使用--ignore-existing
参数。比如,本地已经安装了http-server,但还是想使用远程模块,就用这个参数。
npx --ignore-existing http-server
2.5 noddmon
在使用node的一些比如http模块写web服务器,但是每次改写一点代码都需要重启服务器,开发不是很方便。nodemon可以监听代码的改动自动更新,不需要重启服务器程序就可以看效果。
文档:https://www.npmjs.com/package/nodemon
下载:
npm install -g nodemon
2.6 相关文档
三、模块/包 与CommonJS
Node.js 有三类模块,即内置的模块、第三方的模块、自定义的模块。
3. 1 内置的模块
Node.js 内置模块又叫核心模块,Node.js安装完成可直接使用。如:
const path = require('path')
var extname = path.extname('index.html')
console.log(extname)
3.2 第三方的Node.js模块
第三方的Node.js模块指的是为了实现某些功能,发布的npmjs.org上的模块,按照一定的开源协议供社群使用。如:
npm install chalk
const chalk = require('chalk')
console.log(chalk.blue('Hello world!'))
3.3 自定义的Node.js模块
自定义的Node.js模块,也叫文件模块,是我们自己写的供自己使用的模块。同时,这类模块发布到npmjs.org上就成了开源的第三方模块。
自定义模块是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。
3.3.1 模块定义、接口暴露和引用接口
我们可以把公共的功能 抽离成为一个单独的 js 文件 作为一个模块,默认情况下面这个模块里面的方法或者属性,外面是没法访问的。如果要让外部可以访问模块里面的方法或者属性,就必须在模块里面通过 exports 或者 module.exports 暴露属性或者方法。
m1.js:
const name = 'Liwker'
const sayName = () => {
console.log(name)
}
console.log('module 1')
// 接口暴露方法一:
module.exports = {
say: sayName
}
// 接口暴露方法二:
exports.say = sayName
// exports是对 module.exports 的引用
// 相当于 exports = module.exports
// 所以下面这种是错误的!
/*
exports = {
say: sayName
}
*/
main.js:
// 引用模块
const m1 = require('./m1.')
m1.say()
四、常用内置模块
三、 全局对象 global
JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
后面看到所有的全局变量,例如 console,setTimeout 和 process 是 global 变量的成员。我们甚至可以向全局变量添加成员,使其在任何地方都可用。
// 1. nodejs 里面声明的变量,并不会被挂载带 global 全局对象
let b = 20;
console.log(global.b); //undefined
// 2. 可以向global添加成员,使其在任何地方都可用
global.a = 10;
console.log(a); //10
// 3. 在nodejs执行js文件的过程中,里面也存在 this ,但是这个 this 和 global 并不是相等。
console.log(global === this); //false
// 实际上,在 nodejs 里面的this代表的当前这个 js模块(暂且认为 this 代表当前这个js文件)
process 对象
console.log(process.argv);
// 返回一个数组,前两个值是 node 命令所在位置,被执行 JS 文件的路径,若你执行命令时还有带有参数,依次会填充到此数组中也打印出来。(使用 nodejs 开发命令行的应用,需要获取 命令行的参数,才用得上)
console.log(process.argv.slice(2));
node process.js argv1 argv2
// 打印命令里的后两个参数 [argv1, argv2]
console.log(process.arch); // 打印系统位数 x64
5.6 yarn
Yarn
是于 2016 年 10 月 由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,旨在取代 npm 这种包管理工具。
官网:
https://yarnpkg.com/en/docs
中文参考链接:
https://yarn.bootcss.com/
特点:
-
速度超快
yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。 -
超级安全
在执行代码之前,yarn 会通过算法校验每个安装包的完整性。 -
超级可靠
使用详细、简洁的锁文件格式和明确的安装算法,yarn 能够保证在不同系统上无差异的工作。
安装:
管理员模式运行cmd :npm install -g yarn
常用命令:
npm | yarn |
---|---|
npm init -y | yarn init -y |
npm install 包名 [--save] | yarn add 包名 |
npm uninstall react [--save] | yarn remove [react] |
npm install react --save-dev | yarn add react --dev |
npm update [--save] | yarn upgrade |
npm install -g @vue/cli | yarn global add @vue/cli |
yarn 全局安装后,命令不生效
背景:
- 执行
yarn global add @vue/cli
后,重启bash......
, vue 命令依然不生效 - 而 npm 全局安装(npm install -g @vue/cli)后,命令生效
解决办法:
1.执行如下命令,得出 yarn 全局安装的命令所处的安装目录
yarn global bin
2.复制安装目录至电脑的环境变量中
修改yarn全局安装路径
- 改变 yarn 全局安装位置
#1.改变 yarn 全局安装位置
yarn config set global-folder "你的磁盘路径"
#这里是我的路径
yarn config set global-folder "D:\tools\Yarn\Data"
- 改变 yarn 缓存位置
#2. 改变 yarn 缓存位置
yarn config set cache-folder "你的磁盘路径"
#这里是我的路径
yarn config set cache-folder "D:\tools\Yarn\Cache"
- 改变yarn bin位置
在我们使用全局安装包的时候,会在 “D:\tools\Yarn\Data” 下 生成node_modules\.bin
目录
#3.改变 yarn bin位置
yarn config set prefix "你的磁盘路径"
#这里是我的路径
yarn config set prefix "D:\tools\Yarn"
#安装全局包后,会在设置的路径下生成一个bin文件夹
我们需要将 D:\tools\Yarn\bin
整个目录 添加到系统环境变量中去,否则通过yarn 添加的全局包 在cmd 中是找不到的。
检查当前yarn 的 bin的 位置
yarn global bin
#如果按上面设置好了的就会是 "D:\tools\Yarn\bin"
检查当前 yarn 的 全局安装位置
yarn global dir
#如果按上面设置好了的就会是 "D:\tools\Yarn\Data"
四、模块 使用
4.1 模块规范定义
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
一个js文件就是一个模块,模块的作用域是私有的,内部定义的变量或者函数,只在当前的文件(模块)可以使用
如果别人需要使用我们模块里面的东西,那么有两点要做(以CommonJS 的 Modules 规范: Node.js为例)
- 自己编写的模块,由于模块作用域是私有的,默认情况下,外部是没办法使用的;如果希望别人可以使用,则需要导出
exports
或者module.exports
。 导出的时候,以对象的方式进行导出 - 别人要使用某个模块,则需要先引入该模块,使用
require
引入,引入后需要使用一个变量来接收导入的对象。
对书写格式和交互规则的详细描述,就是模块定义规范(Module Definition Specification):
- AMD 规范: Require.js
- CMD 规范: Sea.js
- CommonJS 的 Modules 规范: NodeJs
- ES6 模块化规范 import ... from ...
4.2 NodeJs 模块化使用
导出数据方式一:
exports.num = num;
exports.sum = sum;
exports.Animal = Animal;
导出数据方式二:
// 通过module.exports 等于一个对象,来导出数据
// 对象可采用es6简化对象的写法
module.exports = {
num,
sum,
Animal
};
导入数据:
// 注意1: 如果要使用某个模块里面的数据,则需要使用 require 关键字进行导入。
// 注意2:在导入用户自己开发的模块的时候,需要加上路径(1. 相对路径(多) 2. 绝对路径) 注意: ./ 必须写上
// 注意3:模块文件的扩展名(后缀名)可以写,也可以不写
// 注意4:导出的模块一般需要使用一个变量来接收,一般把接收的量定义为常量
// 注意5: 定义常量的名称和文件的名称保持一致(这个不是必须,大家都这么做)
const m1 = require("./modules/m1.js");
完整代码:
// 导出,m1.js中:
let num = 10;
function sum(a, b) {
return a+b
}
class Animal{
constructor(){
this.age=0
}
}
// 导出数据方式1:
// exports.num = num;
// exports.sum = sum;
// exports.Animal = Animal;
// 导出数据方式2:
// 通过module.exports 等于一个对象,来导出数据
// 对象可采用es6简化对象的写法
module.exports = {
num,
sum,
Animal
};
//导入,使用模块
const m1 = require("./modules/m1.js");
console.log(m1); //{ num: 10, sum: [Function: sum], Animal: [Function: Animal] }
console.log(m1.sum(10, 20)); // 30
const obj = new m1.Animal();
console.log(obj.age); // 0
4.3 模块里面this的指向问题
exports 实际上是 module.exports 的引用
在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象(在文件里,不是交互终端)
console.log(exports); //{}
console.log(module.exports); //{}
console.log(exports === module.exports); //true exports实际上是module.exports的引用
console.log('this', this); // this {}
console.log(this === exports);// true
// 在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象 并且,交互模式下,没有exports这个对象
console.log(global === this ); //false this不指向全局对象
4.4 nodejs常用内置模块
一般项目中模块分为3种:
- node.js 内置模块
- 自己书写的模块
- 第三方模块(使用一个专门的工具npm进行统一管理)
常用的内置模块如下:
- fs :文件操作
- http :网络操作
- path :路径操作
- querystring :查询参数解析
- url :url 解析
const fs = require("fs");
const http = require('http');
const path = require('path');
const querystring = require('querystring');
const url = require('url');
nodejs内置模块的文档网址:http://nodejs.cn/api/
4.5 path 内置模块
path 模块,处理与路径相关
// 导入模块
const path = require("path");
console.log(__dirname); // 当前执行的文件绝对路径,不包含文件名
console.log(__filename); // 当前执行的文件绝对路径,包含文件名和后缀名
let extname = path.extname( __filename ); // 获取扩展名(后缀名)
console.log(extname);
let baseName = path.basename( __filename ); // 获取文件名(包含后缀名)
console.log(baseName);
let dirname = path.dirname(__filename); //获取目录(路径)
console.log(dirname);
let parse = path.parse(__filename); //获取路径字符串的对象
console.log(parse);
//路径的拼接操作 join
// join 默认相对路径的拼接 ,以当前操作系统路径分割符进行拼接
let fullPath1 = path.join('path.js');
// fullPath1 = path.join(__dirname,'path.js'); //带目录
// fullPath1 = path.join(__dirname,'a','path.js'); //带多级目录
console.log(fullPath1);
4.6 Buffer 数据类型
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像文件流时(文件读写操作),必须使用到二进制数据。因此在 Node.js 中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。说白了,Buffer 类似于一个整数数组。
创建buffer对象 :
let buf1 = Buffer.from([97, 98, 99]); //根据一个数组创建 Buffer 对象
console.log(buf1); //<Buffer 61 62 63> 以16进制存在buffer对象中
console.log(buf1.toString()); // abc
let buf2 = Buffer.from("nodejs"); //根据一个字符串创建 Buffer 对象
console.log(buf2);
console.log(buf2.toString()); // nodejs
let buf3 = Buffer.alloc(10); // 创建了可以存放10个字符的buffer对象
buf3.write("abc"); //按照ASCII表的值,转16进制,存在buffer中
console.log(buf3);
console.log(buf3.toString()); // abc
// 总结: 以后看到 <Buffer ..... > 需要 toString() 才能看到里面的真实数据
4.7 fs 文件系统模块
Node.js 的 API 内置的有两个模块: path 和 fs ,我们使用 JavaScript 代码编写程序运行在 Node.js 环境中就可以操作文件
4.7.1 同步读取文件信息
同步读取:读取的时候,要等文件读取完毕后,才会执行后面的代码 (sync 同步)
// 准备工作
const fs = require("fs");
const path = require("path");
let pathName = path.join(__dirname, 'hello.txt');
//同步读取文件
const content = fs.readFileSync(pathName);
// console.log(content);
// 转换
console.log(content.toString());
const content = fs.readFileSync(pathName, "utf-8");
console.log(content);
4.7.2 异步读取文件信息
不用等待文件读取完毕就会执行后面的代码。所谓异步,就是当前回调函数不用等执行完就可以执行后面的语句。
思考:如何读到后面的数据
答:在读取文件的时候,传递一个回调函数callback,当读取完毕后,回调函数执行,读取后面的数据
const fs = require("fs");
const path = require("path");
let pathName = path.join(__dirname, "hello2.txt");
// console.log(file);
//参数1 要读取的文件
//参数2 设置读取到内容的编码,设置后读到的内容为字符串,如果不传则读到的数据为 buffer
//参数3 回调函数,读取完文件后执行的代码
fs.readFile(pathName, "utf-8",(error, data)=>{
// console.log(error);
// console.log(data);
if(error){
console.log(error);
return;
}
console.log(data);
});
4.7.3 异步写入
const fs = require("fs");
const path = require("path");
let pathName = path.join(__dirname, "hello.txt");
fs.writeFile(pathName, "hello_write111", "utf-8",(error)=>{
console.log("error");
console.log("写完啦");
});
console.log("end");
4.7.4 几个常见方法
const fs = require("fs");
fs.renameSync(旧文件名, 新文件名); //修改文件名
fs.readdirSync(__dirname); //读取当前路径下的文件名列表
let str = "hello";
str.endsWith("lo"); //true 是否以某字符串结尾
str.startsWith("hh"); //false 是否以某字符串开头
str.substring(2,4) //ll 左闭右开区间
str.substring(2) //llo 从下标为2取到结束
4.7.5 小案例
需求:把当前文件夹的js文件的名字都添加前缀 [Liwker]
const fs = require("fs");
let nameList = fs.readdirSync(__dirname);
nameList.forEach(currFileName => {
if(currFileName.endsWith(".js")){
fs.renameSync(currFileName, `[Liwker]${currFileName}`)
}
});
需求:把当前文件夹的名字都删除前缀 [Liwker]
const fs = require("fs");
let nameList = fs.readdirSync(__dirname);
let str1 = "[Liwker]"
nameList.forEach(currFileName => {
if(currFileName.startsWith(str1)){
fs.renameSync(currFileName, currFileName.substring(str1.length))
}
});
4.8 http 模块
4.8.1 http核心模块的使用
四个步骤:
-
导入http模块
-
定义服务器程序端口
-
创建服务器对象
-
调用服务器的监听方法,让服务器监听浏览器请求
// 1、导入http模块
const http = require("http");
// 2、定义服务器程序端口
const port = 8080;// 端口号:1-65535 (有些服务已经有一些默认端口 apache nginx 80 web 服务。 MySQL:3306 MongoDB:27017)
// 注意:一个端口只能被一个服务进行使用,如果这个端口被某个服务使用,其他的服务不能在使用该端口的。这个时候出现端口冲突。如何解决?答:换个端口
// 建议:1-1024 端口(有些系统服务会使用这个范围的端口),不建议程序员自己使用。一般都使用 1024 以后的端口。
// 3、创建服务器对象
const server = http.createServer((request, response)=>{
response.write("hello nodejs"); // 书写响应体内容
response.end() //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务
});
// 4、调用服务器的监听方法,让服务器监听浏览器请求
server.listen(port,(error)=>{
console.log(error);
console.log(`server is running at port ${port}`);
});
//如果需要解决中文乱码,需遵循http协议:
response.setHeader("Content-type","text/html;charset=utf-8");
4.8.2 获取请求的一些信息
const http = require("http");
const url = require("url");
const server = http.createServer((request, response)=>{
//如果需要解决中文乱码,需遵循http协议:
response.setHeader("Content-type","text/html;charset=utf-8");
console.log("------------------------------");
// Get
let requestUrl = request.url; // 获取本次请求的资源路径
console.log(requestUrl);
let method = request.method; // 获取本次请求的方式
console.log(method);
let obj = url.parse( requestUrl, true); // true解析成对象,false解析成字符串
console.log(obj.query); // 获取get请求的查询字符串
// localhost:8080?name=nodejs&age=11 get请求
// Post
//当存在 post 提交数据 data 事件立马执行,postData就是提交过来的数据对象
request.on('data',(postData) => { // 获取post请求的请求参数
console.log(postData.toString());
});
response.write("hello nodejs"); // 书写响应体内容
response.end(); //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务
});
六、ES6模块
6.1 nodejs12版本以下是 不支持ES6模块化规范的解决方案
在项目目录下新建src文件夹,src文件夹下新建m1.js模块和app.js模块:
m1.js模块中到处数据:
export let name = "nodejs";
export let age = 11;
app.js中导入模块:
import {name,age} from "./m1.js"
此时运行app.js会报错!!! SyntaxError: Unexpected token {
注意:nodejs 不支持 es6 模块化规范。
可以把这个代码转换一下,然后把 es6 规范转换为 commonjs 规范
学语法,兼容性如何不用管,可以交给第三方的转换工具(babel-cli 和 browserify)实现
解决:
1、在项目文件夹下生成生成 package.json 文件
yarn init -y 或者 npm init -y
2、安装第三方工具:
在任意目录下执行,全局安装babel-cli 和 browserify:
如果yarn没有安装成功,就用npm
yarn global add babel-cli browserify 或者 npm install babel-cli browserify -g
在自己项目目录下执行:
yarn add babel-preset-es2015 或者 npm install babel-preset-es2015 --save-dev
3、在项目根目录新建 .babelrc 文件 :
{
"presets": [
"es2015"
]
}
4、在项目目录下书写完代码后,执行:
babel src -d lib
// src(源文件夹) lib(目标文件夹)
(如果出现babel 不是内部或者外部命令,请按照第三点最后的yarn 全局安装后,命令不生效的解决办法)
5、运行lib下的app.js即可 node lib\app.js
(记得,修改代码需要执行babel src -d lib命令后,再运行lib下的app.js)
6.2 ES6模块化规范语法
导出数据方式一:
//导出数据方式一:
export let name = "nodejs";
export let age = 11;
导出数据方式二:
let name = "nodejs";
let age = 11;
export {name, age}
针对导出数据的前两种方式的导入数据:
import {name,age} from "./m1.js"
导出数据方式三:
// 默认导出只能写一次
export default {name, age}
导入并使用数据:
import m3 from "./m3"
console.log(m3.name);
console.log(m3.age);
在es6中的默认导出的写法,允许和前面的导出方式一起写:
导出数据:
let name = "nodejs";
let age = 11;
export let email = "nodejs@163.com";
// 默认导出只能写一次
export default {name, age}
导入并使用数据:
import m3, {email} from "./m3"
console.log(m3.name);
console.log(m3.age);
console.log(email);