node.js遵循了CommonJS的模块化规范:
- 导入其它模块使用require()方法
- 模块对外共享成员使用module.exports对象
ES6模块化规范是浏览器端与服务器端通用的模块化开发规范。
- 每个js文件都是一个独立的模块
- 导入其它模块成员使用import关键字
- 向外共享模块成员使用export关键字
在node.js中体验ES6模块化
- 安装v14.15.1或更高版本的node.js
- 在package.json的根节点中添加"type":"module"
ES6模块化用法:
1、默认导出/默认导入
- 默认导出
- 语法:export default { 默认导出的成员 }
-
export default { show, };
- 注意:每个模块中只允许使用唯一的一次export default
- 默认导入
- 语法:import 接收名称 from '模块标识符(路径)'
-
import m from "./m.js";
- 注意:默认导入,接收名称要合法
2、按需导出/按需导入
- 按需导出
- 语法:export 按需导出的成员
-
export function say() {}
- 按需导入
- 语法:import { say } from '模块标识符'
-
import { say } from "./m2.js";
- 注意:每个模块中可以使⽤多次按需导出;按需导⼊的成员名称必须和 按需导出的名称保持⼀致;按需导⼊时,可以使⽤ as 关键字进⾏重命名;按需导⼊可以和默认导⼊⼀起使⽤
3、直接导入并执行模块中的代码
如果只想单纯地执⾏某个模块中的代码,并不需要得到模块中向外共享的成员。此时,可以直接导⼊并执⾏模块代码
import './m3.js'
Promise
回调地狱:多层回调函数的相互嵌套形成回调地狱。
缺点:难维护,可读性差。
Promise的基本概念:
1、Promise是一个构造函数
- 我们可以创建 Promise 的实例 const p = new Promise()
- new 出来的 Promise 实例对象,代表⼀个异步操作
2、Promise.prototype 上包含⼀个 .then() ⽅法
- 每⼀次 new Promise() 构造函数得到的实例对象,
- 都可以通过原型链的⽅式访问到 .then() ⽅法,例如 p.then()
3、.then() ⽅法⽤来预先指定成功和失败的回调函数
- p.then(成功的回调函数,失败的回调函数)
- p.then(result => { }, error => { })
- 调⽤ .then() ⽅法时,成功的回调函数是必选的、失败的回调函数是可选的
then() 方法的特性
如果上⼀个 .then() ⽅法中返回了⼀个新的 Promise 实例对象,则可以通过下⼀个 .then() 继 续进⾏处理。通 过 .then() ⽅法的链式调⽤,就解决了回调地狱的问题。
通过.catch 捕获错误
在 Promise 的链式操作中如果发⽣了错误,可以使⽤ Promise.prototype.catch ⽅法进⾏捕获和处理
如果不希望前⾯的错误导致后续的 .then ⽆法正常执⾏,则可以将 .catch 的调⽤提前
Promise.all() 方法
所有异步任务执行完才执行.then操作。
Promise.race() 方法
Promise.race() ⽅法会发起并⾏的 Promise 异步操作,只要任何⼀个异步操作完成,就⽴即执⾏下⼀步的 .then 操作(赛跑机制)。
async/await
async/await 是 ES8(ECMAScript 2017)引⼊的新语法,⽤来简化 Promise 异步操作。在 async/await 出 现之前,开发者只能通过链式 .then() 的⽅式处理 Promise 异步操作。
thenFs.readFile('./files/1.txt','utf8').then(r1=>{
console.log(r1)
return thenFs.readFile('./files/2.txt','utf8')}).then(
r2=>{
console.log(r2)})
- then 链式调⽤的优点: 解决了回调地狱的问题
- then 链式调⽤的缺点: 代码冗余、阅读性差、 不易理解
async/await 的基本使⽤
import thenFs from 'then-fs'
async function getAllFile() {
const r1 = await thenFs.readFile('./files/1.txt','utf8')
console.log(r1)
const r2 = await thenFs.readFile('./files/2.txt','utf8')
console.log(r1)
}
getAllFile()
async/await 的使⽤注意事项:
- ① 如果在 function 中使⽤了 await,则 function 必须被 async 修饰
- ② 在 async ⽅法中,第⼀个 await 之前的代码会同步执⾏,await 之后的代码会异步执⾏
EventLoop
JavaScript 是单线程的语⾔:如果前⼀个任务⾮常耗时,则后续的任务就不得不⼀直等待,从⽽导致程序假死的问题。
同步任务和异步任务
① 同步任务(synchronous)
- ⼜叫做⾮耗时任务,指的是在主线程上排队执⾏的那些任务
- 只有前⼀个任务执⾏完毕,才能执⾏后⼀个任务
② 异步任务(asynchronous)
- ⼜叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进⾏执⾏
- 当异步任务执⾏完成后,会通知 JavaScript 主线程执⾏异步任务的回调函数
宏任务和微任务
宏任务:
- 异步Ajax请求
- setTimeout、setInterval
- 文件操作
- 其它宏任务
微任务
- Promise.then、.catch和finally
- process.nextTick
- 其它微任务
宏任务和微任务的执行顺序
- 每⼀个宏任务执⾏完之后,都会检查是否存在待执⾏的微任务,
- 如果有,则执⾏完所有微任务之后,再继续执⾏下⼀个宏任务。