ES6模块化(官方方案)

配置

  • node版本必须大于v13.0.0
  • 初始化后在 package.json 的根节点中添加 "type": "module"

    • type的默认值是CommonJS,表示代码只能使用CommonJS语法
      • CommonJS 适用于服务器端的 Javascript 模块化
        • 导出:module.exports = 导出的内容
        • 导入:require(‘模块’)
    • type 配置为 “module” 之后,表示项目代码 只能 使用 ES6模块化语法

      ES6模块化语法

      默认

  • 导出export default 导出的内容

    • 一个模块不能有多个默认导出,最多只能有一个
  • 导入import 变量 from '模块/路径'

    按需

  • 导出

    • 可以既有默认导出又有按需导出(不冲突)
    • 需要导出那个变量,只需要在前面加上export关键字
  • 导入
    • import {变量1,变量2,变量3} from '模块/路径'
    • 导入里面的变量名,必须和导出的一致
    • 如果这个变量名已经被声明 可以在导入的后面使用as 别名
    • import * as obj from '模块/路径'
      • 将所有内容全部导入 成一个对象(默认导出的在对象中是default:值

        直接导入

        如果只想单纯地执行某个模块中的代码,并不需要得到模块中向外共享的成员此时,可以直接导入并执行模块代码,示例代码如下:
        import '模块的路径'
        实际的项目中,我们使用这种语法,导入css、less、图片等等资源

Promise

Promise能够处理异步程序

回调地狱

JS中或node中,都大量的使用了回调函数进行异步操作,而异步操作什么时候返回结果是不可控的,如果我们希望几个异步请求按照顺序来执行,那么就需要将这些异步操作嵌套起来,嵌套的层数特别多,就会形成 回调地狱 或者叫做 横向金字塔
ES6模块化和Promise(必学) - 图1


语法:

  • let p = new Promise( (resolve, reject) => {这里写异步任务})
    • 将错误传递给 reject ,将正确结果传递给resolve
  • p.then(res => {}, err => {})
    • p.then(函数1,函数2)
    • 函数1:获取正确的结果
    • 函数2:获取错误的结果,(可选)
      1. const fs = require('fs')
      2. // 基础语法
      3. let p = new Promise((resolve, reject) => {
      4. fs.readFile('./文本.txt', 'utf-8', (err, data) => {
      5. // 将错误传递给 reject ,将正确结果传递给resolve
      6. err ? reject(err) : resolve(data.length)
      7. })
      8. })
      9. // then方法获取结果
      10. p.then(
      11. res => { // 函数1获取正确结果
      12. console.log(res)
      13. },
      14. err => { // 函数2获取错误结果
      15. console.log(err)
      16. })

Promise三种状态

  • 最初状态:pending,等待中,此时promise的结果为 undefined;
  • 当 resolve(value) 调用时,达到最终状态之一:fulfilled,(成功的)完成,此时可以获取结果value
  • 当 reject(error) 调用时,达到最终状态之一:rejected,失败,此时可以获取错误信息 error

    当达到最终的 fulfilled 或 rejected 时,promise的状态就不会再改变了。

当调用 resolve的时候,Promise 将到达最终的状态。 达到最终状态之后,Promise的状态就不会再改变了。
多次调用 resolve 函数,只有第一次有效,其他的调用都无效。

  1. let p = new Promise((resolve,reject) => {
  2. resolve(123)
  3. resolve(456) //这次调用无效
  4. })
  5. p.then(res => {
  6. console.log(res) //输出123
  7. })

Promise同步异步?

  • new Promise()是同步执行的
  • 获取结果时(调用 resolve 触发 then方法时)是异步的
    1. console.log(1)
    2. let p = new Promise((resolve,reject) => {
    3. console.log(2)
    4. resolve(3)
    5. console.log(4)
    6. })
    7. console.log(5)
    8. p.then(res => {
    9. console.log(res)
    10. })
    11. console.log(6)
    12. // 输出结果为 1 2 4 5 6 3 只有3变换位置
    13. // 证明只有then方法是异步 new Promise() 里面时同步的

.then方法的链式调用

p.then().then().then
前一个then返回一个Promise对象,Promise对象中resolve值会被下一个then得到
then的链式调用,保证了输出顺序

  1. let P = new Promise((resolve,reject) => {
  2. resolve(100)
  3. })
  4. let P1 = new Promise((resolve,reject) => {
  5. resolve(200)
  6. })
  7. let P2 = new Promise((resolve,reject) => {
  8. resolve(300)
  9. })
  10. P.then(res => {
  11. console.log(res)
  12. return P1
  13. }).then(res => {
  14. console.log(res)
  15. return P2
  16. }).then(res => {
  17. console.log(res)
  18. })
  19. // 输出 100 200 300
  20. // 结论:前一个then返回一个Promise对象,Promise对象中resolve值会被下一个then得到
  21. // 结论:then的链式调用,保证了输出顺序

使用第三方模块读取文件

  • npm init - y
  • npm i then-fs 安装then-fs模块
  • then-fs 将 内置的fs模块封装了,读取文件后,返回 Promise 对象,省去了我们自己封装
  • 修改 package.json ,添加 “type”: “module” 表示使用ES6的模块化语法 ```javascript // then-fs 是一个第三方模块 // 它把内置的 then-fs 模块重新封装了一下 // 封装之后,每个方法都返回Promise对象 // 这样的话,咱们就不要new Promise了,直接调用方法,就可以得到Promise对象了 const {readFile} = require(‘then-fs’)

let P = readFile(‘./a.text’,’utf-8’) let p1 = readFile(‘./b.txt’,’utf-8’)

P.then(res => { console.log(res) return p1 }).then(res => { console.log(res) })

  1. ---
  2. <a name="MzPsW"></a>
  3. ### async和await
  4. 代替then语法用来获取结果
  5. <a name="XqgjA"></a>
  6. #### 语法
  7. - `async function fn() {let res = await Promise对象}`
  8. - async 后面必须跟着函数
  9. - await 只能出现在 async的函数内
  10. - await 后面跟着 Promise对象
  11. ```javascript
  12. const {readFile} = require('then-fs')
  13. let p1 = readFile('./a.text','utf-8')
  14. let p2 = readFile('./b.txt','utf-8')
  15. async function fn() {
  16. let res1 = await p1
  17. let res2 = await p2
  18. console.log(res1,res2);
  19. }
  20. fn()

async特点

  • async修饰的函数,总是返回一个Promise对象

    • 函数内的返回值,将自动包装在resolve内
    • 比如返回了123 输出查看是 Promise { 123 }

      await特点

  • await 这个关键字只能出现在 async 的函数内部

  • await 需压等待Promise执行完毕,会暂停函数的执行,它下面的所有代码是异步的,会最后执行

错误处理

.catch方法

在 .then 方法的链式调用的末尾加 .catch() 统一处理错误
.catch(err => {console.log(err)})

try … catch 语句

使用async和await时,出现错误try会抛出catch会捕捉错误
async function fn() {try {}catch(e) {}}

  1. const { readFile } = require('then-fs');
  2. let p1 = readFile('./files/a.txt', 'utf-8');
  3. let p2 = readFile('./files/bbbbb.txt', 'utf-8'); // 故意把这里的路径写错
  4. let p3 = readFile('./files/c.txt', 'utf-8');
  5. // 获取结果,方案一 ------------- 使用then -----------
  6. p1.then(res => {
  7. console.log(res.length)
  8. return p2;
  9. }).then(res => {
  10. console.log(res.length);
  11. return p3;
  12. }).then(res => {
  13. console.log(res.length)
  14. }).catch(err => {
  15. console.log(err);
  16. });
  17. // 获取结果,方案二 --------- 使用async和await -----------
  18. async function abc() {
  19. try {
  20. // try 表示试试,试一试,尝试。这里放正常的代码
  21. let r1 = await p1;
  22. let r2 = await p2; // p2这里出错了,相当于 throw err,抛出错误。并且会终止这段代码执行
  23. let r3 = await p3;
  24. console.log(r1.length, r2.length, r3.length);
  25. } catch (e) {
  26. console.log(e); // e就是上面try里面,抛出的错误
  27. }
  28. }
  29. abc();

宏任务和微任务、事件循环

宏任务

任务(代码) 宏任务 环境
script 宏任务 浏览器
事件 宏任务 浏览器
网络请求(Ajax) 宏任务 浏览器
setTimeout() 定时器 宏任务 浏览器 / Node
fs.readFile() 读取文件 宏任务 Node

微任务

.thena( () => { **微任务** }) | **await下面的代码**
微任务(microtask)是宏任务中的一个部分,它的执行时机是在同步代码执行之后,下一个宏任务执行之前

事件循环

  • 把宏任务循环,循环按以下顺序
    • 1.同步任务
      • 同步任务先执行,遇到微任务会先跳过
    • 2.微任务
      • 同步任务执行完毕后,执行微任务
    • 3.DOM操作

面试题分析

1

  1. console.log(1)
  2. setTimeout(function() {
  3. console.log(2)
  4. }, 0)
  5. const p = new Promise((resolve, reject) => {
  6. resolve(1000)
  7. })
  8. p.then(data => {
  9. console.log(data)
  10. })
  11. console.log(3)

2

  1. console.log(1)
  2. setTimeout(function() {
  3. console.log(2)
  4. new Promise(function(resolve) {
  5. console.log(3)
  6. resolve()
  7. }).then(function() {
  8. console.log(4)
  9. })
  10. })
  11. new Promise(function(resolve) {
  12. console.log(5)
  13. resolve()
  14. }).then(function() {
  15. console.log(6)
  16. })
  17. setTimeout(function() {
  18. console.log(7)
  19. new Promise(function(resolve) {
  20. console.log(8)
  21. resolve()
  22. }).then(function() {
  23. console.log(9)
  24. })
  25. })
  26. console.log(10)

3

  1. console.log(1)
  2. setTimeout(function() {
  3. console.log(2)
  4. }, 0)
  5. const p = new Promise((resolve, reject) => {
  6. console.log(3)
  7. resolve(1000) // 标记为成功
  8. console.log(4)
  9. })
  10. p.then(data => {
  11. console.log(data)
  12. })
  13. console.log(5)

4

  1. new Promise((resolve, reject) => {
  2. resolve(1)
  3. new Promise((resolve, reject) => {
  4. resolve(2)
  5. }).then(data => {
  6. console.log(data)
  7. })
  8. }).then(data => {
  9. console.log(data)
  10. })
  11. console.log(3)

5

  1. setTimeout(() => {
  2. console.log(1)
  3. }, 0)
  4. new Promise((resolve, reject) => {
  5. console.log(2)
  6. resolve('p1')
  7. new Promise((resolve, reject) => {
  8. console.log(3)
  9. setTimeout(() => {
  10. resolve('setTimeout2')
  11. console.log(4)
  12. }, 0)
  13. resolve('p2')
  14. }).then(data => {
  15. console.log(data)
  16. })
  17. setTimeout(() => {
  18. resolve('setTimeout1')
  19. console.log(5)
  20. }, 0)
  21. }).then(data => {
  22. console.log(data)
  23. })
  24. console.log(6)

6

  1. <script>
  2. console.log(1);
  3. async function fnOne() {
  4. console.log(2);
  5. await fnTwo(); // 右结合先执行右侧的代码, 然后等待
  6. console.log(3);
  7. }
  8. async function fnTwo() {
  9. console.log(4);
  10. }
  11. fnOne();
  12. setTimeout(() => {
  13. console.log(5);
  14. }, 2000);
  15. let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
  16. console.log(6);
  17. resolve();
  18. console.log(7);
  19. })
  20. setTimeout(() => {
  21. console.log(8)
  22. }, 0)
  23. p.then(() => {
  24. console.log(9);
  25. })
  26. console.log(10);
  27. </script>
  28. <script>
  29. console.log(11);
  30. setTimeout(() => {
  31. console.log(12);
  32. let p = new Promise((resolve) => {
  33. resolve(13);
  34. })
  35. p.then(res => {
  36. console.log(res);
  37. })
  38. console.log(15);
  39. }, 0)
  40. console.log(14);
  41. </script>