一、ES6模块化
1.1 概念与规则
ES6 模块化规范是浏览器端与服务器端通用的模块化开发规范
ES6 模块化规范中定义:
- 每个 js 文件都是一个独立的模块
- 导入其它模块成员使用 import 关键字
- 向外共享模块成员使用 export 关键字
1.2 在node.js体验es6模块化
配置如下:
- 确保安装v14.15.1或更高版本的node(node -v查看版本)
- npm init -y初始化包管理配置文件
- 在package.json添加"type":"module"
1.3 ES6模块化的基本语法
- 默认导入与默认导出
- 按需导入与按需导出
- 直接导入并执行模块中的代码
1.3.1 默认导出与导入
export default 默认导出的成员
import 接收名称 from '模块标识符'
每个模块只能使用一次export default
导入的接收名称任意
1.3.2 按需导入与导出
export 按需导出的成员
import {接收名称} from ‘模块标识符’
每个模块中可以使用多次按需导出
按需导入的成员名称必须和按需导出的名称保持一致
按需导入时,可以使用 as 关键字进行重命名
按需导入可以和默认导入一起使用
1.3.3 直接导入并执行模块中的代码
import '代码文件路径'
二、Promise
回调地狱
多层回调函数的相互嵌套
缺点:耦合性强、可读性差
2.1 基本概念
- Promise是一个构造函数
const p = new Promise()
- Promise.prototype上包含.then()方法
- .then()用来预先指定成功和失败的回调函数
p.then(result=>{}, error=>{})
2.2 then-fs使用
2.2.1 基本使用
先装包 npm i then-fs
import thenFs from 'then-fs'
//无法保证读取文件的顺序
thenFs.readFile('./file/1.txt', 'utf8').then((r1) => {console.log(r1)})
thenFs.readFile('./file/2.txt', 'utf8').then((r2) => {console.log(r2)})
thenFs.readFile('./file/3.txt', 'utf8').then((r3) => {console.log(r3)})
因为上述代码是异步执行,无法保证读取文件的顺序,所以需要优化
下面通过链式调用解决了无法顺序读取文件的问题
import thenFs from 'then-fs'
//.then()的返回值是新的promise对象
thenFs.readFile('./file/1.txt', 'utf8').then((r1) => {
console.log(r1)
return thenFs.readFile('./file/2.txt', 'utf8')
})//链式调用
.then((r2) => {
console.log(r2)
return thenFs.readFile('./file/3.txt', 'utf8')
})
.then((r3) => {
console.log(r3)
})
2.2.2 通过catch捕获错误
import thenFs from 'then-fs'
//.then()的返回值是新的promise对象
thenFs.readFile('./file/11.txt', 'utf8').then((r1) => { //如果没有11.txt
console.log(r1)
return thenFs.readFile('./file/2.txt', 'utf8')
})//链式调用
.then((r2) => {
console.log(r2)
return thenFs.readFile('./file/3.txt', 'utf8')
})
.then((r3) => {
console.log(r3)
})
.catch(err => {
console.log(err.message)
})
2.2.3 Promise.all()
Promise.all() 方法会发起并行的 Promise 异步操作,等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制)
import thenFs from 'then-fs'
const promiseArr = [
thenFs.readFile('./file/1.txt', 'utf8'),
thenFs.readFile('./file/2.txt', 'utf8'),
thenFs.readFile('./file/3.txt', 'utf8')
]
//数组中promise实例的顺序就是最后结果的顺序
Promise.all(promiseArr).then(result => {
console.log(result)
})
2.2.4 Promise.race()
Promise.race() 方法会发起并行的 Promise 异步操作,只要任何一个异步操作完成,就立即执行下一步的 .then 操作(赛跑机制)
三、async/await
async/await 是 ES8(ECMAScript 2017)引入的新语法,用来简化 Promise 异步操作
3.1 基本使用
import thenFs from 'then-fs'
async function getAllFiles(){
const r1 = await thenFs.readFile('./file/1.txt', 'utf8')
console.log(r1)
const r2 = await thenFs.readFile('./file/2.txt', 'utf8')
console.log(r2)
const r3 = await thenFs.readFile('./file/3.txt', 'utf8')
console.log(r3)
}
getAllFiles()
① 如果在 function 中使用了 await,则 function 必须被 async 修饰
② 在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行
四、EventLoop
4.1 单线程语言
JS是单线程执行的语言,同一时刻只能做同一件事情
缺点:如果某一个任务非常耗时,则后续任务必须等待,则会导致程序假死
4.2 同步任务和异步任务
4.2.1 同步任务
又叫做非耗时任务,指的是在主线程上排队执行的那些任务
只有前一个任务执行完毕,才能执行后一个任务
4.2.2 异步任务
又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境(浏览器/node)进行执行
当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
4.3 同步任务和异步任务执行过程
① 同步任务由 JavaScript 主线程次序执行
② 异步任务委托给宿主环境执行
③ 已完成的异步任务对应的回调函数,会被 加入到任务队列中等待执行
④ JavaScript 主线程的执行栈被清空后,会 读取任务队列中的回调函数,次序执行
⑤ JavaScript 主线程不断重复上面的第 4 步
五、宏任务和微任务
JavaScript 把异步任务又做了进一步的划分为宏任务和微任务
① 宏任务(macrotask)
- 异步 Ajax 请求、
- setTimeout、setInterval、
- 文件操作
- 其它宏任务
② 微任务(microtask)
- Promise.then、.catch 和 .finally
- process.nextTick
- 其它微任务