本文探讨了 JavaScript 中 Promise 的使用是否会将同步代码变为异步代码。通过分析 Promise 的基本概念以及两个示例函数(一个使用 setTimeout 模拟异步操作,另一个使用 while 循环模拟同步阻塞),文章指出 Promise 本身并不改变代码的同步或异步性质。即使代码被封装在 Promise 中,同步操作仍然会阻塞主线程,而异步操作则不会。

在 JavaScript 开发中,Promise 是一个强大的工具,用于处理异步操作。但很多人会误以为,将代码封装到 Promise 中,原本的同步代码就会变成异步代码。本文将通过具体示例来探讨这一问题。

Promise 的基本概念

Promise 是一个表示异步操作最终完成或失败的对象,它有三种状态:pending(进行中)、fulfilled(已完成)和 rejected(已失败)。它提供了处理成功或失败结果的方法。

示例代码分析

以下是两个函数示例:

const a = arg => { return new Promise(resolve => { setTimeout(() => { console.log(arg) resolve(arg) }, 1000) }) } const b = arg => { return new Promise(resolve => { let now = Date.now() while (Date.now() - now < 1000) { // do nothing } console.log(arg) resolve(arg) }) } 

 

  • 函数 a 使用 setTimeout 模拟异步操作,延迟 1000 毫秒后执行。
  • 函数 b 使用 while 循环阻塞主线程约 1000 毫秒。

接下来,我们在一个异步自执行函数中调用这些函数:

;(async () => { // a 执行 console.time('time a') await Promise.all([a(1), a(2)]) console.timeEnd('time a') // 预期输出: time a: 接近 1000ms // b 执行 console.time('time b') await Promise.all([b(1), b(2)]) console.timeEnd('time b') // 预期输出: time b: 接近 2000ms })()

执行行为分析

函数 a 的执行

  • a(1) 和 a(2) 立即返回 Promise,并在 1000 毫秒后完成。
  • Promise.all 等待所有 Promise 完成,总时间接近 1000 毫秒。
  • setTimeout 是非阻塞的,不会阻塞主线程。

函数 b 的执行

  • b(1) 和 b(2) 立即返回 Promise,但内部的 while 循环阻塞主线程约 1000 毫秒。
  • Promise.all 依次执行 b(1) 和 b(2),总时间约为两个阻塞时间的总和,即 2000 毫秒。

结论

  • Promise 本身不会改变代码的同步或异步性质。
  • 函数 a 中的异步操作不会阻塞主线程。
  • 函数 b 中的同步操作仍然会阻塞主线程。

Promise 是一个强大的工具,用于处理异步操作的结果,但它本身并不改变代码的同步或异步性质。理解这一点对于编写高效且响应迅速的 JavaScript 应用至关重要。希望本文能帮助你更好地理解 Promise 和同步/异步代码之间的关系。