我的日常开发记录日志
首页
  • Laravel
  • Thinkphp
  • Swoole
  • Workman
  • php
  • HTML
  • CSS
  • JavaScript
  • Vue
  • ES6
  • 小程序
  • Mysql
  • Redis
  • Es
  • MongoDb
  • Git
  • Composer
  • Linux
  • Nginx
  • Docker
  • Vpn
  • 开发实战
  • 开发工具类
  • 友情链接
💖关于
💻收藏
  • 分类
  • 标签
  • 归档数据
GitHub (opens new window)

我的日常开发记录日志

never give up
首页
  • Laravel
  • Thinkphp
  • Swoole
  • Workman
  • php
  • HTML
  • CSS
  • JavaScript
  • Vue
  • ES6
  • 小程序
  • Mysql
  • Redis
  • Es
  • MongoDb
  • Git
  • Composer
  • Linux
  • Nginx
  • Docker
  • Vpn
  • 开发实战
  • 开发工具类
  • 友情链接
💖关于
💻收藏
  • 分类
  • 标签
  • 归档数据
GitHub (opens new window)
  • html

  • css

  • javascript

  • vue

    • Vue
    • vue3基本类型ref初始化
    • vue3中尖括号和冒号的使用细则
    • vue3中为什么使用const不使用let
    • vue3中watch和compute是
    • route-view的作用
    • 关于import使用问题
    • 顶层await的理解
      • 这意味着在使用顶层 await 时,JavaScript 会暂停当前模块的执行,直到 Promise 被解决或拒绝。
        • 示例分析
        • 执行流程
        • 关键点
        • 错误处理示例
      • 总结
      • 顶层 await 的作用是等待异步操作完成,但它的行为和传统意义上的“阻塞”不同。下面将详细解释顶层 await 的非阻塞特性,以及它与阻塞的区别。
      • 1. 顶层 await 的行为
        • 示例
      • 2. 阻塞的定义
      • 3. 比较
      • 4. 总结
      • 下面是一个更详细的示例,以帮助说明顶层 await 的行为,以及它是如何在等待异步操作时不阻塞主线程的。
        • 示例:顶层 await vs. 传统阻塞
        • 输出结果
        • 关键点分析
        • 详细执行步骤
        • 执行过程
        • 总结
    • js中的常见的异步操作
    • vue中use理解
    • vue中config使用
    • vue中的env环境使用
    • 在html中直接使用vue
    • vue3中setup
    • vue3中ref和reactive的区别
    • vue3中watch
    • vue3中vite-config
    • vue3中组件的props类型
    • vite创建项目
    • vite使用tailwindcss
  • 小程序

  • Es6

  • 前端
  • vue
窝窝侠
2024-11-14

顶层await的理解

# 这意味着在使用顶层 await 时,JavaScript 会暂停当前模块的执行,直到 Promise 被解决或拒绝。

# 示例分析

const fetchData = async () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("数据加载完成");
        }, 1000);
    });
};

// 使用顶层 await
const data = await fetchData(); // 这里会等待 fetchData 执行完成
console.log(data); // 只有当 fetchData 完成后,才会执行这行代码
1
2
3
4
5
6
7
8
9
10
11

# 执行流程

  1. 调用 fetchData():当执行到 await fetchData() 时,JavaScript 会调用该函数。
  2. Promise 创建:fetchData 返回一个 Promise,setTimeout 模拟一个异步操作。
  3. 等待完成:在这段时间内,JavaScript 会暂停当前模块的执行,等待 Promise 被解决。
  4. Promise 解决:一秒后,setTimeout 调用 resolve(),使得 Promise 变为已解决状态。
  5. 继续执行:一旦 Promise 被解决,JavaScript 将继续执行下一行代码,即 console.log(data),并输出 "数据加载完成"。

# 关键点

  • 非阻塞性:虽然顶层 await 会暂停当前模块的执行,但主线程仍然能够处理其他任务(如用户输入、其他事件等),这使得 JavaScript 的运行不会完全阻塞。
  • 错误处理:如果 fetchData 中发生错误,您应该使用 try/catch 来捕获这些错误,以避免未处理的 Promise 拒绝。

# 错误处理示例

try {
    const data = await fetchData();
    console.log(data);
} catch (error) {
    console.error("发生错误:", error);
}
1
2
3
4
5
6

在这个示例中,任何在 fetchData 执行过程中抛出的错误都将被捕获,并打印出相应的错误信息。

# 总结

顶层 await 确实会等待异步操作完成后,才会继续执行后面的代码

# 顶层 await 的作用是等待异步操作完成,但它的行为和传统意义上的“阻塞”不同。下面将详细解释顶层 await 的非阻塞特性,以及它与阻塞的区别。

# 1. 顶层 await 的行为

  • 暂停当前模块:当您使用顶层 await 时,当前模块的执行会在该 await 处暂停,直到 Promise 被解决。这意味着在该 Promise 完成之前,模块内的后续代码不会执行。

  • 非阻塞主线程:尽管当前模块暂停了,但其他任务(如事件处理、其他异步操作等)仍然可以在主线程上继续进行。JavaScript 的事件循环机制确保了这一点。

# 示例

const fetchData = async () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("数据加载完成");
        }, 1000);
    });
};

// 使用顶层 await
const data = await fetchData(); // 这里会暂停当前模块的执行
console.log(data); // 在 fetchData 完成后执行
1
2
3
4
5
6
7
8
9
10
11

在这个示例中,虽然 await fetchData() 暂停了当前模块的代码执行,但主线程可以处理其他任务,如响应用户输入等。

# 2. 阻塞的定义

  • 阻塞:在计算机科学中,阻塞指的是一个操作会使得当前线程无法继续执行其他任务,直到该操作完成。这通常会导致应用程序在等待操作完成期间变得无响应。

# 3. 比较

  • 顶层 await:

    • 暂停当前模块的执行,等待 Promise 完成。
    • 不会阻塞主线程,允许其他事件和操作继续进行。
  • 传统阻塞操作:

    • 会导致整个线程停止,无法执行其他代码,直到操作完成。
    • 可能导致用户界面无响应。

# 4. 总结

顶层 await 使得代码在等待异步操作时能够暂停执行,但这种暂停不会影响主线程的执行。因此,虽然它在模块内部的行为类似于阻塞,但从整个 JavaScript 运行环境的角度来看,顶层 await 不是传统意义上的阻塞。

# 下面是一个更详细的示例,以帮助说明顶层 await 的行为,以及它是如何在等待异步操作时不阻塞主线程的。

# 示例:顶层 await vs. 传统阻塞

假设我们要模拟一个场景,其中我们从网络获取数据和处理用户输入。我们将使用顶层 await 来等待数据加载,同时在等待期间允许其他操作进行。

# 1. 顶层 await 示例

// 模拟从网络获取数据的函数
const fetchData = async () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("数据加载完成");
        }, 2000); // 2秒后完成
    });
};

// 使用顶层 await 加载数据
const data = await fetchData(); // 暂停当前模块执行,等待数据加载
console.log(data); // 输出: 数据加载完成
console.log("继续执行其他代码..."); // 这行代码在数据加载完成后执行
1
2
3
4
5
6
7
8
9
10
11
12
13

在这个示例中:

  • fetchData 函数模拟了一个需要 2 秒的网络请求。
  • await fetchData() 会暂停当前模块的执行,直到 Promise 被解决。
  • 一旦 Promise 完成,程序将打印数据并继续执行后面的代码。

# 2. 加入用户输入处理

为了展示顶层 await 不会阻塞主线程,我们可以在等待数据加载时模拟用户输入。

// 模拟从网络获取数据的函数
const fetchData = async () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("数据加载完成");
        }, 2000); // 2秒后完成
    });
};

// 模拟用户输入
const handleUserInput = () => {
    console.log("用户输入: 按下了一个键...");
};

// 使用顶层 await 加载数据
console.log("开始加载数据...");
const data = await fetchData(); // 这里会暂停当前模块的执行
console.log(data); // 输出: 数据加载完成
console.log("继续执行其他代码..."); // 在数据加载完成后执行

// 用户输入操作可以在后台进行
setTimeout(handleUserInput, 1000); // 模拟在 1 秒后输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 输出结果

  1. 开始加载数据...
  2. 用户输入: 按下了一个键...
  3. 数据加载完成
  4. 继续执行其他代码...

# 关键点分析

  • 用户输入:setTimeout(handleUserInput, 1000) 模拟用户在 1 秒内输入。这行代码将会在顶层 await 暂停时执行,显示出主线程并没有被阻塞。
  • 顶层 await 行为:虽然 await fetchData() 暂停了当前模块的执行,但它不会影响其他任务(如用户输入)的处理。

# 详细执行步骤

让我们逐步分析之前的代码示例,以清楚了解执行顺序:

// 模拟从网络获取数据的函数
const fetchData = async () => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("数据加载完成");
        }, 2000); // 2秒后完成
    });
};

// 模拟用户输入
const handleUserInput = () => {
    console.log("用户输入: 按下了一个键...");
};

// 使用顶层 await 加载数据
console.log("开始加载数据...");
const data = await fetchData(); // 这里会暂停当前模块的执行
console.log(data); // 输出: 数据加载完成
console.log("继续执行其他代码..."); // 在数据加载完成后执行

// 用户输入操作可以在后台进行
setTimeout(handleUserInput, 1000); // 模拟在 1 秒后输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 执行过程

  1. 开始加载数据:当程序执行到 console.log("开始加载数据...") 时,输出此消息。

  2. 调用 fetchData():

    • await fetchData() 被调用,创建了一个 Promise,该 Promise 会在 2 秒后被解决。
    • 此时代码暂停:由于 await 被调用,当前模块的执行被暂停,等待 Promise 完成。
  3. 设定用户输入:

    • setTimeout(handleUserInput, 1000) 被调用,并设置一个 1 秒的定时器。在 1 秒后,handleUserInput 将会被调用,输出用户输入的消息。
  4. Promise 解决:

    • 经过 2 秒后,fetchData 中的 setTimeout 调用 resolve("数据加载完成"),使得 Promise 被解决。
    • 此时,代码执行恢复,继续执行 console.log(data) 和 console.log("继续执行其他代码...")。
  5. 输出数据:

    • 在 Promise 被解决后,程序输出数据 "数据加载完成",然后输出 "继续执行其他代码..."。

# 总结

  • await 的作用:使用 await 时,代码在该行暂停,等待 Promise 完成。因此,在 Promise 完成之前,后续代码不会执行。
  • 用户输入的模拟:在 await 暂停期间,如果有其他事件(如用户输入)可以执行,即使原本的代码在逻辑上是顺序执行的,JavaScript 的事件循环机制仍然允许处理这些其他操作。

因此,console.log(data); 和 console.log("继续执行其他代码..."); 并不会在 await 被调用后立即执行,而是会在 Promise 被解决后才执行,这就是为什么它们的输出是在 handleUserInput 后面的原因。

在线编辑 (opens new window)
上次更新: 2025/02/25, 18:30:54
关于import使用问题
js中的常见的异步操作

← 关于import使用问题 js中的常见的异步操作→

最近更新
01
showprocess用法
04-29
02
vue3中尖括号和冒号的使用细则
04-29
03
sd使用
02-22
更多文章>
🖥️

© 2025窝窝侠 💌 豫ICP备20005263号-2 🛀 Theme by 💝 Vdoing && 小胖墩er

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×