async-await-事件循环

发布于:2022-12-29 ⋅ 阅读:(614) ⋅ 点赞:(0)

async关键字用于声明一个函数是异步的,搭配await实现函数的异步执行,在async函数中,如果没有await关键字,则函数与普通函数没有什么区别,函数代码将会同步执行。

当异步函数有返回值时,和普通的函数会有区别。

1、异步函数也可以有返回值,返回值会包裹到Peomise.resolve中。

2、如果异步函数返回的是一个Promise,Promise.resolve的状态将会由Promise决定。

3、如果异步函数的返回值实现了thenable,那么会由返回值的then来决定。

如果在async中抛出了异常throw,那么函数不会像普通函数一样报错,而是会作为Peomise的reject来传递错误信息。

await关键字在普通函数中不可以使用,在await关键字后会返回一个promise,await会等到promise变成fulfilled状态时,之后继续执行异步函数。

  1. 如果await后是一个普通的值,那么会直接返回这个值。
  2. 如果await后是一个thenable对象,那么会根据对象的then方法来决定后续的值。
  3. 如果await后面的表达式返回的是reject状态,那么会将这个reject结果作为函数的promise的reject值。

事件循环:

js主线程执行同步代码,将异步代码交由其它线程执行,其它线程执行完毕后将异步代码添加到事件队列中,js引擎定时执行事件队列中代码,将代码放入js线程中执行。

宏任务队列-----macrotask queue---定时器-Ajax-dom-ui rendering

微任务队列-----microtask queue---queueMicrotask--- promise then

规范:在执行宏任务之前需保证微任务队列已经清空。

面试题一:

setTimeout(function () {
  console.log("setTimeout1");
  new Promise(function (resolve) {
    resolve();
  }).then(function () {
    new Promise(function (resolve) {
      resolve();
    }).then(function () {
      console.log("then4");
    });
    console.log('then2');
  })
})

new Promise(function (resolve) {
  console.log('promise1');
  resolve();
}).then(function () {
  console.log("then1");
})

setTimeout(function () {
  console.log("setTimeout2");
})

console.log(2);

queueMicrotask(() => {
  console.log("queueMicrotask1");
})

new Promise(function (resolve) {
  resolve();
}).then(function () {
  console.log("then3");
})

        上题中按照jsv8引擎的执行逻辑,promise原理及实现不难得出函数的输出结果,按照mainscript-->microltask--->macroltask顺序执行。

 

面试题二:

async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}

async function async2() {
  console.log('async2');
}
console.log('script start');
setTimeout(() => {
  console.log('settimeout');
}, );
async1();
new Promise((resolve, reject) => {
  console.log('promise1');
  resolve();
}).then(() => {
  console.log('promise2');
})

        此题关键在于了解async的特性及await关键字的作用,在含有await的async中,同一代码块中await后的所有代码将被放置返回的promise的then方法中执行,也即await后的代码将被加载进微任务队列,同时不含await的async函数与普通函数没有任何差别,由此不难得出结果为:

面试题三:

Promise.resolve().then(() => {
  console.log(0);
  return Promise.resolve(4)
}).then(res => console.log(res))

Promise.resolve().then(() => {
  console.log(1);
}).then(() => {
  console.log(2);
}).then(() => {
  console.log(3);
}).then(() => {
  console.log(5);
}).then(() => {
  console.log(6);
}).then(() => {
  console.log(7);
})

        此题主要注意的是原生的Promise的then方法中,如果返回的是一个普通值,则返回的值会被立即调用并赋值给resolve函数,如果返回的是一个thenable,则then方法将会被放入到微队列中执行,如果返回的是一个Promise.resolve,则会再加一次微任务队列。即微任务后移,Promise.resolve本身是执行then方法,而then方法本身是在微任务队列中执行,同时return Promise.resolve时是将resolve调用的返回值 作为上级then中resolve的参数传递,调用外层then方法时本身是在微队列里面,所以函数的执行顺序是要在微队列中下移两次。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到