前端Vue中async/await、promise 和setTimeout工作原理和执行顺序

本文详细解释了在前端Vue中,async/await、Promise和setTimeout在JavaScript中的执行顺序,强调了它们如何在微任务和宏任务中交互,以及await如何影响Promise的执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前端Vue中async/awaitPromise 和 setTimeout 在 JavaScript 中都是处理异步操作的方法,但它们的工作原理和执行顺序有所不同。以下是它们的执行顺序和关系的简要说明:

  1. 同步代码执行:在任何异步操作开始之前,首先会执行所有的同步代码。

  2. setTimeout:setTimeout 设置的回调函数会被放入 JavaScript 的事件队列中,等待当前同步代码执行完毕后才会执行。即使 setTimeout 的延迟设置为 0,它的回调函数也不会立即执行,而是会在同步代码执行完后,等待事件队列空闲时才会执行。

  3. Promise:Promise 对象表示一个异步操作的最终完成(或失败)及其结果值。Promise 的执行顺序依赖于其状态。如果 Promise 已经处于 fulfilled 或 rejected 状态,那么其 .then() 或 .catch() 中的回调函数会立即执行。如果 Promise 还在 pending 状态,那么它的回调函数会被放入微任务队列中,等待当前同步代码和事件队列中的任务执行完毕后才会执行。

  4. async/await:async 函数总是返回一个 Promise 对象。await 关键字用于等待一个 Promise 的解决或拒绝,并返回 Promise 的解决值。async/await 的执行顺序也依赖于 Promiseasync 函数内部的代码会同步执行,直到遇到 await 关键字。在 await 关键字处,async 函数的执行会暂停,并等待 Promise 的解决。一旦 Promise 解决,async 函数的执行会恢复,并继续执行后面的代码。由于 async/await 的执行是基于 Promise 的,因此它们通常会被放入微任务队列中,与 Promise 的回调函数一起执行。

在 JavaScript 中,async/await、promise 和setTimeout的执行顺序如下:


1. 当遇到async函数时,会返回一个promise对象,而不会立即执行其内部代码。当async函数中有await时,会暂停函数的执行,等待await后面的表达式的promise对象完成(要么resolved,要么rejected)。await后面的表达式的promise对象完成后,会根据其状态决定下一步的操作。如果是resolved状态,则将其返回值作为await表达式的结果;如果是rejected状态,则抛出错误。

2. 当遇到Promise对象时,会立即执行其内部代码。Promise的then方法也会被封装成微任务,等待当前宏任务执行完毕后执行。

3. 当遇到setTimeout时,会将回调函数放入不同的等待队列,优先级低于await和promise。当定时器到期后,回调函数会被加入到宏任务队列中等待执行。


根据以上执行顺序,在async/await、promise和setTimeout共存的情况下,微任务优先于宏任务执行。下面是一个代码示例:


// 定义一个 async 函数 async1,在其中使用 await 等待 async2 函数执行完成

async function async1() {   console.log('async1 start');   await async2();   console.log('async1 end');}
// 定义一个 async 函数 async2async function async2() {   console.log('async2');}
// 定义一个 Promise 对象console.log('script start');
setTimeout(() => {   console.log('setTimeOut');}, 0);
async1();
new Promise(function (resolve) {   console.log('promise1');   resolve();}).then(function () {   console.log('promise2');});console.log('script end');

上面代码执行打印顺序:

script startasync1 start async2 promise1script end promise2 async1 endsetTimeOut

上面代码执行顺序说明

1、执行console.log('script start'),输出script start;

2、执行setTimeout,是一个异步动作,放入宏任务异步队列中;

3、执行async1(),输出async1 start,继续向下执行;

4、执行async2(),输出async2,并返回了一个promise对象,await让出了线程,把返回的promise加入了微任务异步队列,所以async1()下面的代码也要等待上面完成后继续执行;

5、执行 new Promise,输出promise1,然后将resolve放入微任务异步队列;

6、执行console.log('script end'),输出script end;

7、到此同步的代码就都执行完成了,然后去微任务异步队列里去获取任务

8、然后执行resolve(new Promise的),输出了promise2。

9、接下来执行resolve(async2返回的promise返回的),输出了async1 end。

10、最后执行setTimeout,输出了settimeout。

欢迎加入“前端组件开发学习”交流群,一起学习成长!可关注  “前端组件开发” 公众号后,私信后申请入群。

d848d5658a07453c843277846948c608.png

### 解析 Vue2 中 `async/await` 不生效的原因 在 Vue2 项目中遇到 `async/await` 关键字不起作用的情况,通常是因为以下几个原因: - **未正确配置 Babel 插件**:Vue2 默认可能并未完全支持 ES7 的特性如 `async/await`。为了使这些新语法能够正常工作,需要安装并配置相应的 Babel 插件来转换代码。 ```bash npm install --save-dev @babel/plugin-transform-runtime ``` 接着,在 `.babelrc` 文件里添加插件配置项: ```json { "plugins": ["@babel/plugin-transform-runtime"] } ``` 这一步骤确保了浏览器兼容性旧版本 JavaScript 环境下的正常使用[^4]。 ### 正确编写带有 `async/await` 的生命周期钩子 当尝试在一个组件的生命周期钩子里(比如 `mounted()`)使用 `async/await` 时,应该注意整个函数体都需要声明为异步函数,并且内部调用其他异步逻辑的地方要加 `await` 关键词。下面是一个修正后的例子说明如何正确实现这一点: ```javascript export default { name: 'MyComponent', async mounted() { // 将 lifecycle hook 定义成 async function try { let res = await this.getSysTime(); // 使用 await 等待 promise 结果 setInterval(async () => { // 如果要在定时器内继续使用 async/await,则同样需定义为 async 函数 await this.request(); }, 1000); } catch (error) { console.error('Error fetching system time:', error); } }, methods: { async getSysTime() { // 假设这是一个返回 Promise 的 API 请求方法 return new Promise(resolve => setTimeout(() => resolve({ currentTime: Date.now().toString()}), 500) ); }, request(){ // 这里模拟发起一次 HTTP 请求或其他耗时操作 return new Promise((resolve,reject)=>{ setTimeout(()=>{ Math.random()>0.5 ? resolve("success"):reject("failure"); },Math.floor(Math.random()*1000)+500)//随机延迟时间 }); } } }; ``` 上述代码片段展示了如何通过将 `mounted` 生命周期钩子标记为 `async` 并在其内部合理运用 `try/catch` `await` 来捕获异常以及等待异步任务完成[^2]。 ### 验证环境设置与依赖库更新 除了调整编译工具链外,还需确认所使用的 Node.js 版本支持最新 ECMAScript 标准的开发环境。对于某些特定场景下可能出现的问题,可以通过升级相关依赖包至最新稳定版来进行修复,特别是那些涉及 Webpack 或者 Vue CLI 构建系统的部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端组件开发

你的钟意将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值