Promise async/await EventLoop 宏任务/微任务

一、Promise

1.1回调地狱。

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

setTimeout(()=>{
  console.log('延时1秒');
  setTimeout(()=>{
    console.log('延时2秒');
    setTimeout(()=>{
      console.log('延时3秒')
    },3000)
  },2000)
},1000)

回调地狱的缺点:

①代码耦合性太强,牵一发而动全身,难以维护。

②大量冗余的代码相互嵌套,代码的可读性差。

1.2如何解决回调地狱。

使用promise 构造函数 解决回调地狱的问题,ES6中新增了Promise的概念。

1.3Promise的基本概念

1.3.1 Promise是一个构造函数

我们可以创建Promise的实例 cont p = new Promise()

new 出来的Promise 的实例对象,代表一个异步操作。

1.3.2Promise.prototype上包含一个.then()方法

每次new Promise()构造函数得到的实例对象

都可以通过原型链的方式访问到.then()方法 例如p.then()

1.3.3 .then()方法 用来预先指定成功和失败的回调函数。

p.then(成功的回调函数,失败的回调函数)

p.then(result =>{},error=>{})

调用.then()方法时,成功的回调函数是必选的,失败的回调函数是可选的

2.基于回调函数按顺序读取文件的内容

fs.readFild('./files/1.txt', 'utf8', (err1, r1) => {
  if (err1) return console.log(err1.message);
  fs.readFild('./files/2.txt', 'utf8', (err2, r3) => {
    if (err2) return console.log(err2.message);
    fs.readFild('./files/3.txt', 'utf8', (err3, r3) => {
      if (err3) return console.log(err3.message);
    });
  });
});

3基于 then-fs 读取文件内容

由于 node.js官方提供的fs模块仅支持以回调函数的方式读取文件,不支持Promise的调用方式,因此,需要先运行如下的命令,安装 then-fs 第三方包

npm install then-fs

3.1 then-fs 的基本使用。

调用then-fs提供的readFile()方法,可以异步的读取文件的内容,它的返回值是Promise的实例对象,因此可以调用.then()方法 为每个Promise异步操作指定成功和失败之后的回调函数。

import thenFs from 'then-fs';

thenFs.readFile('./files/1.txt', 'utf8').then((r1) => {
  console.log(r1);
});
thenFs.readFile('./files/2.txt', 'utf8').then((r2) => {
  console.log(r2);
});
thenFs.readFile('./files/3.txt', 'utf8').then((r3) => {
  console.log(r3);
});

3.2 .then()方法的特性

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

3.3 基于Promise按顺序读取文件的内容

Promise支持链式调用, 从而来解决回调地狱的问题

import thenFs from 'then-fs';

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

二、async/await

1.什么是async/await?

async/await是ES8 中新引入的语法, 用来简化Promise异步操作,在async/await 出现之前,开发者只能通过链式.then()方式处理 Promise异步操作

.then 链式调用的优点:解决了回调地狱的问题

.then 链式调用的缺点:代码冗余 阅读性差 不易理解

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

getAllFile();

3.async/wait 的使用注意事项

①如果在function中使用了 await 则function 必须被async修饰

②在async 方法中,第一个await之前的代码会被同步执行,await之后的代码会被异步执行。

import thenFs from 'then-fs';

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');
}

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



结果
A
B
C
111 222 333
D

三、EventLoop(事件循环)

1.java 是一门单线程的语言。

JavaScript 是一门单线程执行的编程语言。也就是说,同一时间只能做一件事情。

单线程执行任务队列的问题:

如果前一个任务非常耗时,则后续的任务就不得不一直等待,从而导致程序假死的问题。

2.同步任务和异步任务:

为了防止某个耗时任务导致程序假死的问题, JavaScript 把待执行的任务分为了两类:

  1. 同步任务 (synchronous)

又叫做非耗时任务,指的是在主线程上排队执行的那些任务

只有前一个任务执行完毕,才能执行后一个任务

  1. 异步任务(asynchronous)

又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行

当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数

例子:ajax

3.同步任务和异步任务的执行过程。

4.EventLoop的基本概念、经典面试题

JavaScript 主线程从“任务队列”中读取异步任务的回调函数,放到执行栈中依次执行。这个过程是循环不断的, 所以整个的这种运行机 制又称为 EventLoop (事件循环) 。

console.log('a');
setTimeout(function () {
  console.log('b');
}, 2000);

setTimeout(function () {
  console.log('c');
}, 0);

console.log('d');
正确的输出结果: ADCB。其中:
1.  A 和 D 属于同步任务。会根据代码的先后顺序依次被执行 
2.  C 和 B 属于异步任务。它们的回调函数会被加入到任务队列中,等待主线程空闲时再执行 

四、宏任务/微任务

1.什么是宏任务和微任务?

JavaScript把异步任务又做了进一步的划分,划分成了宏任务和异步任务。

①宏任务(macrotask)

异步Ajax请求

setTimemout setInterval

文件操作

其他宏任务

②微任务(microtask)

Promise.then .catch和.finally

process.nextTick

其他微任务

2.宏任务和微任务的执行顺序。

 

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

3.去银行办业务的场景

 案例:

 答案:2431

 

 答案 156234789

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值