Promise 封装同步代码后是否就变为异步?
本文探讨了 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
和同步/异步代码之间的关系。