首页 > 编程语言 >JavaScript中的异步编程:Promise、async 和 await

JavaScript中的异步编程:Promise、async 和 await

时间:2024-08-07 15:28:23浏览次数:12  
标签:异步 JavaScript await resolve Promise error async

JavaScript中的异步编程:Promise、async 和 await

在 JavaScript 中,Promiseasyncawait 是处理异步操作的关键技术。这些技术允许开发者以更清晰、更可维护的方式编写异步代码,特别是在面对复杂的异步逻辑时。下面我会详细解释每个概念并展示它们是如何协同工作的。

Promise

Promise 是 JavaScript 中的一个对象,代表了异步操作的最终完成(或失败)及其结果值。一个 Promise 对象可能处于以下三种状态之一:

  1. Pending(进行中):异步操作尚未完成。
  2. Fulfilled(已成功):异步操作已完成,Promise 获得了一个值。
  3. Rejected(已失败):异步操作失败,Promise 获得了一个原因(错误)。

创建 Promise

Promise 是通过其构造函数创建的,该构造函数接受一个执行器函数,这个函数接受两个参数:resolvereject

const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        if (/* some condition */) {
            resolve("Data received");
        } else {
            reject("Error occurred");
        }
    }, 1000);
});

使用 Promise

Promise 提供了 .then(), .catch(), 和 .finally() 方法来处理成功、失败和完成(无论成功还是失败)的情况:

promise
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.error(error);
    })
    .finally(() => {
        console.log("Done");
    });

Promise.race()

在JavaScript中,Promise.race() 是一个静态方法,用于处理多个 Promise 对象。它接受一个 Promise 数组作为参数,并返回一个新的 Promise。这个新 Promise 的结果由传入的 Promise 中最先解决(无论是成功还是失败)的那一个决定。

Promise.race() 可以在多个异步操作中竞争,返回最先完成的操作的结果。这在处理具有超时限制的请求或者当你只需要多个异步操作中的第一个结果时非常有用。

let promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, 'One');
});

let promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'Two');
});

Promise.race([promise1, promise2]).then((value) => {
    console.log(value);  // 输出: "Two" 因为 promise2 更快地解决了
});

在这个例子中,promise2 具有更短的延时(100毫秒),因此它比 promise1 更快地解决,所以 Promise.race() 返回的 Promise 也解决为 “Two”。

应用场景

  • 超时处理Promise.race() 常用于实现超时逻辑,例如可以让一个异步操作与一个延时的 Promise 竞争,如果异步操作在超时时间内未完成,则超时的 Promise 获胜,这样可以通知用户操作超时。
  • 快速失败:如果有多个异步操作,你只需要任意一个完成的结果,而某些操作可能会异常缓慢或卡住,使用 Promise.race() 可以在第一个 Promise 完成时立即得到结果,无需等待其他。

注意事项

使用 Promise.race() 时,一旦有一个 Promise 完成(无论是解决还是拒绝),整个 race 就结束了,其他的 Promise 仍会继续执行,但它们的结果将不会再被处理。这意味着你可能需要确保所有参与的 Promise 在必要时都有适当的清理逻辑,避免潜在的资源浪费或内存泄漏。

网络请求示例

function fetchData(url) {
    // 返回一个新的Promise
    return new Promise((resolve, reject) => {
        // fetch 是JavaScript中的一个内建函数,用于发起网络请求。它是Web API的一部分,可用于从网络获取资源,如文档或JSON数据。fetch 函数返回一个 Promise 对象,可以用来处理HTTP响应并访问其内容。
        fetch(url)
            .then(response => {
                if (response.ok) { // 检查响应状态
                    return response.json(); // 解析JSON数据
                } else {
                    throw new Error('Network response was not ok.');
                }
            })
            .then(data => resolve(data)) // 成功时,解析的数据通过resolve传递
            .catch(error => reject(error)); // 失败时,错误通过reject传递
    });
}

// 使用fetchData函数
fetchData('https://api.example.com/data')
    .then(data => {
        console.log('Data retrieved:', data);
    })
    .catch(error => {
        console.error('Failed to fetch data:', error);
    });

async 和 await

asyncawait 是基于 Promise 的语法糖,使得异步代码的编写和阅读更像是同步代码。

async

async 关键字用于声明一个函数是异步的。任何一个 async 函数都会返回一个 Promise 对象。如果函数返回值不是 Promise,该返回值将自动被包装成一个已解决的 Promise

async function fetchData() {
    return "Data";
}
// 等价于
function fetchData() {
    return Promise.resolve("Data");
}

await

await 关键字用于等待一个 Promise 解决,并暂停 async 函数的执行直到 Promise 被解决或拒绝。使用 await 可以使异步代码读起来像同步代码。

async function asyncFunction() {
    try {
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error(error);
    }
}

在上面的例子中,await fetchData() 会暂停执行,直到 fetchData() 返回的 Promise 被解决。如果 Promise 被拒绝,错误将被 catch 块捕获。

并行执行

当有多个异步操作可以同时进行时,使用 Promise.all 来并行执行这些操作,这样可以显著提高效率。

async function loadMultipleData() {
    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
    console.log(data1, data2);
}

在上面的例子中,fetchData1()fetchData2() 会同时开始执行,await Promise.all(...) 会等待两者都完成。

总结

使用 Promiseasyncawait,可以使异步代码的结构更加清晰,更易于理解和维护。这些工具解决了传统回调地狱的问题,提供了一种更加强大和灵活的方式来处理 JavaScript 中的异步逻辑。

标签:异步,JavaScript,await,resolve,Promise,error,async
From: https://blog.csdn.net/a2272062968/article/details/140992685

相关文章

  • JavaScript 数组方法
    JavaScript数组的力量隐藏在数组方法中。把数组转换为字符串JavaScript方法toString()把数组转换为数组值(逗号分隔)的字符串。join()方法也可将所有数组元素结合为一个字符串。它的行为类似toString(),但是您还可以规定分隔符<pid="demo"></p><script>varfruits......
  • JavaScript 中布尔值的创建
    <!DOCTYPEhtml><htmllang="en"><body><script> //CreateaBooleanobjectusingthenewkeywordandtheBoolean()constructor. varmyBoolean1=newBoolean(false);//Usingnewkeyword. console.log(typeofmyBoolean1);......
  • JavaScript (二十六)——JavaScript 代码规范
    目录JavaScript代码规范变量名空格与运算符代码缩进语句规则对象规则每行代码字符小于80命名规则HTML载入外部JavaScript文件文件扩展名所有的JavaScript项目适用同一种规范。JavaScript代码规范代码规范通常包括以下几个方面:变量和函数的命名规则......
  • Javascript——NaN有什么用法
    简介在JavaScript中,NaN(NotaNumber)是一个特殊的值,用来表示非数字的结果,例如一个不合法的数学运算的结果。根据IEEE754浮点数标准,NaN不等于任何值,包括它自己。这意味着NaN是唯一一个与自身不相等的值,所以表达式NaN===NaN返回false。判断NaN如果你需要检测一......
  • JavaScript 中的“this”几种不同含义
    在JavaScript中,“ this ”指的是当前正在执行代码的对象。其值由函数的调用方式动态确定,这意味着它可以根据上下文而变化。1.全球背景在全局上下文中(即任何函数或对象之外),“ this”指的是全局对象。在浏览器中,“ this”是窗口对象,而在Node.js中,它是全局对象。2.对象......
  • 【TS】 TypeScript声明文件:打通JavaScript和TypeScript的桥梁
     TypeScript声明文件的讲解: TypeScript声明文件(DeclarationFile)在TypeScript项目中具有举足轻重的地位,它是连接TypeScript严格的类型系统与外部无类型或类型不明确的JavaScript代码的关键纽带。 声明文件的核心价值在于为TypeScript编译器提供必要的类型信息......
  • JavaScript(二十二)——JavaScript this 关键字
    目录方法中的this单独使用this函数中使用this(默认)函数中使用this(严格模式)事件中的this对象方法中绑定显式函数绑定面向对象语言中this表示当前对象的一个引用。但在JavaScript中this不是固定不变的,它会随着执行环境的改变而改变。在方法中,this表示该方......
  • JavaScript 中的闭包和事件委托
    包(Closures)闭包是JavaScript中一个非常强大的特性,它允许函数访问其外部作用域中的变量,即使在该函数被调用时,外部作用域已经执行完毕。闭包可以帮助我们实现数据的私有化、封装和模块化,使代码更简洁、易读和可维护。闭包的定义简单来说,闭包是指有权访问另一个函数作......
  • 我可以将 Python 与 javascript 结合起来用于网站或应用程序吗
    我不知道如果j添加Python和javascript可以吗我尝试过。但决定在继续之前询问一下是否可以继续但是如果我只使用javascript还是只使用python会更好吗?我只需要建议或答案将Python与Javascript结合用于网站或应用程序不仅完全可行,而且也是一种非常常见的做法!二者......
  • Python 网络抓取与请求和美丽的汤被需要 javascript 阻止
    我正在尝试从网站上抓取文本。我使用简单的代码:requests.get(url_here)。我的代码直到最近才有效。现在,当我使用请求时,我收到一条消息,而不是获取网站的文本:“该网站需要启用JavaScript!您使用的浏览器不支持JavaScript,或者已关闭JavaScript。“我已验证我的浏览器确实......