Promise,async,await 面试题

目录

推荐先看Promise 相关知识点

5,面试题

1

结果 1,5,2,3,4

js 复制代码
const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log(2);
    resolve();
    console.log(3);
  });
});

promise.then(() => {
  console.log(4);
});

console.log(5);

因为 then() 中的回调函数虽然是微任务,但也得等到 promise 变为 fulfilled 状态才会执行。

2

结果 1,3,2

js 复制代码
async function fun() {
  console.log(1); // 同步
  const n = await 2;
  console.log(n);
}

fun();
console.log(3);

因为 fun() 函数中的同步语句会直接执行,异步的才会延迟执行。

js 复制代码
// 相当于
function fun() {
  console.log(1);
  Promise.resolve(2).then((n) => {
    console.log(n);
  })
}

3

结果 1,4,2,3

js 复制代码
async function fun() {
  console.log(1); // 同步
  const n = await 2;
  console.log(n);
}

(async () => {
  await fun();
  console.log(3);
})();

console.log(4);

同理,立即执行函数执行后,await fun() 中的同步代码先执行,异步代码进入微队列等待执行。所以先输出 1 后输出 4。

4

结果 Promise {<pending>},Promise {<pending>},4,1,3,1

js 复制代码
async function fun1() {
  return 1;
}

async function fun2() {
  const n = await fun1();
  console.log(n); // 1
  return 2; // 没用被用到
}

async function fun3() {
  const n = fun2(); // 注意没有 await
  console.log(n);
  return 3;
}

fun3().then((n) => {
  console.log(n); // n 是 fun3 的返回值 3
});

fun3();

console.log(4);

1,先看同步代码的执行。

  • 第1个 fun3() 执行,会执行 fun2(),再执行 await fun1(),会将 async fun1 返回的 Promise 对象的后续处理,放到微队列中等待执行(任务1)。
js 复制代码
const n = await fun1();
console.log(n);

// 相当于
new Promise((resolve) => {
  resolve(1)
}).then((n) => {
  console.log(n);
})
  • 因为 fun2async 修饰,而且还有异步代码,所以此时 fun2() 执行的结果是一个 pending 状态的 Promise 对象,所以输出 Promise {<pending>}fun3() 的后续处理:then() 的回调函数进入微队列等待执行(任务2)。
  • 第2个 fun3() 执行,再次输出 Promise {<pending>},并添加微任务3
  • 输出 4

2,接下来看异步代码的执行。

  • 执行微队列中的任务1输出 1,任务2输出 3,任务3输出 1

5

结果 1

js 复制代码
Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)

参考 3.2 的知识点。then() 的参数不是函数,说明没有对前一个任务做后续处理,相当于无效代码。

js 复制代码
// 等价
Promise.resolve(1).then(console.log)

6

结果:promise1,undefined,end,promise2,promise3,promise4,Promise {<pending>},after1

js 复制代码
var a
var b = new Promise((resolve, reject) => {
  console.log('promise1')
  setTimeout(() => {
    resolve()
  }, 1000)
})
  .then(() => {
    console.log('promise2')
  })
  .then(() => {
    console.log('promise3')
  })
  .then(() => {
    console.log('promise4')
  })

a = new Promise(async (resolve, reject) => {
  console.log(a)
  await b
  console.log(a)
  console.log('after1')
  await a
  resolve(true)
  console.log('after2')
})
console.log('end')

注意,ba 都是右边 Promise 执行的结果。右边先执行,再赋值给左边的变量。

1,先看同步代码执行

  • 执行 b 右边的表达式,输出 promise1setTimeout 的回调函数进入宏队列等待执行。此时 b 被赋值为一个 pending 状态的 Promise 对象。
  • 执行 a 右边的表达式,输出 undefined(此时 a 未赋值)。
  • 执行 await b,因为此时 bpending 状态,所以后续代码都不会执行,所以 a 也被赋值为一个 pending 状态的 Promise 对象
  • 输出 end

2,再看异步代码执行

  • 没有微队列,所以执行宏队列中 setTimeout 的回调函数,将 b 变为 fulfilled 状态,接着执行后续 3个 then(),依次输出 promise2promise3promise4
  • 现在 b 变为 fulfilled 状态,所以 await b 执行完成,开始执行后续代码。
  • 注意到 a 现在还是一个 pending 状态的 Promise 对象,所以输出 Promise {<pending>} ,再输出 after1
  • 执行 await a,将永远等待,因为没有更改状态的机会。

7

结果 script start,async1 start,async2,p1,script end,async1 end,p2,settimeout

js 复制代码
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')
}, 0)

async1()

new Promise(function (resolve) {
  console.log('p1')
  resolve()
}).then(function () {
  console.log('p2')
})

console.log('script end')

1,先看同步代码执行

  • 输出 script startsetTimeout 的回调函数进入宏队列等待执行。
  • 执行 async1(),输出 async1 start
  • 执行 await async2() 中的同步代码,输出 async2await async2() 之后的代码,相当于在 then() 的回调函数中执行,所以进入微队列等待。
js 复制代码
await async2()
console.log('async1 end')

async function async2() {
  console.log('async2')
}

// 相当于
new Promise((resolve) => {
  console.log('async2')
  resolve()
}).then(() => {
  console.log('async1 end')
})
  • 输出 p1then() 的回调函数进入微队列等待。
  • 输出 script end

2,再看异步代码执行。

  • 先执行微队列中的任务,输出 async1 end,再输出 p2
  • 再执行宏队列中的任务,输出 settimeout

以上。

相关推荐
竹林81841 分钟前
用 wagmi v2 + viem 监听链上事件,我踩了三天坑终于搞懂了实时日志与历史补全
javascript
Momo__44 分钟前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
只一1 小时前
😭从回调地狱到 async/await:一文打通 Ajax 与 JS 异步编程
javascript
程序员小富1 小时前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇1 小时前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇1 小时前
React中的forwardRef
前端·react.js·面试
槑有老呆1 小时前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马1 小时前
Verilog开发常见问题汇总解析
前端
子兮曰1 小时前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端