ES6模块化和异步编程

ES6模块化和异步编程

为什么使用模块化?

规范代码,降低沟通的成本,方便各个模块之间的相互调用,利人利己。

回顾:Node.js 中如何实现模块化 :

  • 遵循 CommonJS 的模块化规范
  • 导入其它模块使用 require() 方法
  • 模块对外共享成员使用 module.exports 对象

ES6 模块化规范中定义:

  • 每个 js 文件都是一个独立的模块
  • 导入其它模块成员使用 import 关键字
  • 向外共享模块成员使用 export 关键字

在 node.js 中体验 ES6 模块化

node.js > v14.15.1 

在文件夹下初始化包配置文件:

npm init -y

package.json 里添加 "type": "module" 节点,设置为 ES6 模块化规范即可体验。

ES6 模块化的基本语法

  1. 默认导出与默认导入

    export default 默认导出的成员:

    默认导入:

    import ml from./01_m1.js'
    

    注意: 每个模块中,只允许使用唯一的一次 export default,否则会报错。

  2. 按需导出与按需导入

    export 按需导出的成员

    按需导入: import { s1 } from ‘模块标识符’

    注意:

    • 按需导入的成员名称必须和按需导出的名称保持一致

    • 模块中可以使用多次按需导入。

  3. 直接导入并执行模块中的代码

    //当前文件模块为05_m3.js
    
    //在当前模块中执行一个for循环操作
    for(leti=0;i<3;i++{
    console.1og(i)
    }
    
    //直接导入并执行模块代码,不需要得到模块向外共享的成员
    import./05_m3.js
    

Promise

回调地狱问题:

多层回调函数的相互嵌套,就形成了回调地狱。

QQ截图20211104132703

Promise 解决回调地狱

Promise 基本概念 :
  • Promise 是一个构造函数
  • 每new 出一个Promise 实例对象,都代表一个异步操作
  • Promise.prototype(原型) 上包含一个 .then() 方法,通过原型链访问。
.then () 方法:
  • p.then( 成功的回调函数,失败的回调函数)
    • p.then (result => { }, error => { })
  • 调用 .then() 方法时,成功的回调函数是必选的、失败的回调函数是可选的。
. then() 方法的特性:

如果上一个 .then() 方法中返回了一个新的 Promise 实例对象,则可以通过下一个 .then() 继续进行处理。通 过 .then() 方法的链式调用,就解决了回调地狱的问题。

【实例】有文件1、2、3.txt, 里面内容依次是111、222、333 ;依次按顺序读取文件,并输出:

使用 then-fs 提供的 readFile() 方法,可以异步地读取文件的内容,它的返回值是 Promise 的实例对象。

npm install then-fs
import thenFs from 'then-fs'

//1.返回值是Promise的实例对象
thenFs.readFile('./files/1.txt','utf8')
	//2.通过.then为第一个Promise实例指定成功之后的回调函数
	.then((r1)=>{
    	console.log(r1)
    	//3.在第一个.then中返回一个新的Promise实例对象
		return thenFs.readFile('./files/2.txt','utf8')
})
// 4.继续调用.then,为上一个then的返回值(新的Promise实例)指定成功之后的回调函数
.then((r2) =>{
    console.log(r2)
    //5.在第二个.then中再返回一个新的Promise实例对象
	return thenFs.readFile('./files/3.txt','utf8')
})
 // 6.继续调用。then,为上一个.then的返回值(新的Promise实例)指定成功之后的回调函数     
.then((r3)=>{
         console.log(r3)                         
})
通过 .catch 捕获错误
import thenFs from 'then-fs'

thenFs.readFile('./files/1111.txt','utf8')   //文件不存在,后面三个then都不执行
	.then((r1)=>{
    	console.log(r1)
		return thenFs.readFile('./files/2.txt','utf8')
})
.then((r2) =>{
    console.log(r2)
	return thenFs.readFile('./files/3.txt','utf8')
})    
.then((r3)=>{
         console.log(r3)                         
})
.catch(err =>{
	console.log(err.message)  // 捕获错误信息并数出
})

如果不希望前面的错误导致后续的 .then 无法正常执行,则可以将 .catch 的调用提前

import thenFs from 'then-fs'

thenFs.readFile('./files/1111.txt','utf8')   
	.catch(err =>{  // 捕获并输出错误
	console.log(err.message)  // 因为错误被及时处理,不影响后续 then 执行
})
    .then((r1)=>{
    	console.log(r1)   // undefined
		return thenFs.readFile('./files/2.txt','utf8')
})
.then((r2) => {
  console.log(r2)  // 222
	return thenFs.readFile('./files/3.txt','utf8')
})    
.then((r3)=>{
         console.log(r3)     // 333                      
})
.all() 和 .race()

Promise.all() 方法:

  • 等所有的异步操作全部结束后才会执行下一步的 .then 操作(等待机制

    import thenFs from 'then-fs'
    
    //1.定义一个数组,存放3个读文件的异步操作
    const promiseArr = [
      thenFs.readFile('./files/1.txt', 'utf8'),
      thenFs.readFile('./files/2.txt', 'utf8'),
      thenFs.readFile('./files/3.txt', 'utf8'),
    ]
    //2.将Promise的数组,作为Promise.all()的参数
    Promise.all(promiseArr)
      .then(([r1, r2, r3]) => {
        //2.1所有文件读取成功(等待机制)
        console.log(r1, r2, r3)
      })
      .catch(err => {
        //2.2捕获Promise异步操作中的错误
        console.log(err.message)
      })
    

Promise.race() 方法:

  • 只要任何一个异步操作完成,就立即执行下一步的 .then 操作(赛跑机制

    import thenFs from 'then-fs'
    
    const promiseArr = [
      thenFs.readFile('./files/1.txt', 'utf8'),
      thenFs.readFile('./files/2.txt', 'utf8'),
      thenFs.readFile('./files/3.txt', 'utf8'),
    ]
    
    Promise.race(promiseArr)
      .then(([r1, r2, r3]) => {
        // 只要任何一个异步操作完成,就立即执行成功的回调函数(赛跑机制)
        // 只输出一文件的数据  
        console.log(r1, r2, r3)
      })
      .catch(err => {
        console.log(err.message)
      })
    

async/await

async/await 简化 Promise 异步操作, 直接返回值。

import thenFs from 'then-fs'

//按照顺序读取文件1,2,3的内容

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(r2)
const r3=await thenFs.readFile('./files/3.txt','utf8')
console.log(r3)
}

getA11File()
async / await 的使用注意事项:
  • 如果在 function 中使用了 await,则 function 必须被 async 修饰 !
  • 在 async 方法中,第一个 await 之前的代码会同步执行,await 之后的代码会异步执行:
console.log('A');
async function getAllFile(){
  console.log('B');
const r1 =await thenFs.readFile('./files/1.txt','utf8')
console.log(r1)

const r2 =await thenFs.readFile('./files/2.txt','utf8')
console.log(r2)

const r3 =await thenFs.readFile('./files/3.txt','utf8')
console.log(r3)
console.log('D');
}

getA11File()
console.log('C');

输出结果:

A
B
C
111 222 333
D

EventLoop 事件循环

JavaScript 是一门**单线程**(同一时间只能做一件事情) 执行语言。

同步任务和异步任务

为了防止耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了同步和异步任务。

同步任务:

  • 只有前一个任务执行完毕,才能执行后一个任务
  • 在主线程上排队执行

异步任务:

  • 异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
  • JavaScript 委托给宿主环境进行执行

图解 EventLoop

Snipaste_2021-11-04_15-32-16

宏任务和微任务

什么是宏任务和微任务?

QQ截图20211104154619

  1. 宏任务(macrotask)
    • 异步 Ajax 请求
    • setTimeout
    • setInterval
    • 文件操作
  2. 微任务(microtask)
    • Promise.then、.catch 和 .finally
    • process.nextTick

执行顺序

每一个宏任务执行完之后,都会检查是否存在待执行的微任务, 如果有,则执行完所有微任务之后,再继续执行下一个宏任务。

经典案例:

  1. 宏任务(macrotask)
    • 异步 Ajax 请求
    • setTimeout
    • setInterval
    • 文件操作
  2. 微任务(microtask)
    • Promise.then、.catch 和 .finally
    • process.nextTick

执行顺序

每一个宏任务执行完之后,都会检查是否存在待执行的微任务, 如果有,则执行完所有微任务之后,再继续执行下一个宏任务。

经典案例:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OooooYi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值