【Web前端】Promise的使用

Promise是异步编程的核心概念之一。代表一个可能尚未完成的操作,并提供了一种机制来处理该操作最终的成功或失败。具体来说,Promise是由异步函数返回的对象,能够指示该操作当前所处的状态。

当Promise被创建时,它会处于“待定”(Pending)状态,这意味着操作尚未完成。在这个阶段,Promise对象可以通过其提供的方法来注册回调函数,以便在操作最终完成后进行相应的处理。一旦操作完成,Promise的状态会变为“已兑现”(Fulfilled),表示成功;或者变为“已拒绝”(Rejected),表示失败。

除了基本的状态管理,Promise还提供了链式调用的能力,使得开发者可以以更加清晰和可读的方式进行异步操作的组合。例如,可以使用.then()方法处理成功的结果,使用.catch()方法处理错误,甚至可以通过.finally()方法执行一些清理工作,无论操作是成功还是失败。

a3296ed54c5f4b6188aead8b3a9e4910.jpeg


一、什么是 Promise

Promise 是一个代表异步操作最终完成(或失败)及其结果值的对象。它有三种状态:

  • Pending(待定): 初始状态,既不是成功,也不是失败。
  • Fulfilled(已兑现): 操作成功完成。
  • Rejected(已拒绝): 操作失败。

一旦 Promise 被 fulfilled 或 rejected,它的状态就会被锁定,后续的状态无法再改变。


Promise 的基本构造

Promise是通过 ​​new Promise()​​ 构造函数创建的。这个构造函数接受一个执行器(executor)函数作为参数,该函数接收两个参数:​​resolve​​ 和 ​​reject​​。通过调用 ​​resolve​​ 来标记Promise对象状态为已兑现(fulfilled),而通过调用 ​​reject​​​ 则将其标记为已拒绝(rejected)。

const myPromise = new Promise((resolve, reject) => {// 模拟异步操作const success = true; // 假设操作成功if (success) {resolve('操作成功'); // 标记Promise为已兑现} else {reject('操作失败'); // 标记Promise为已拒绝}
});

Promise 的使用

一旦创建了Promise对象,可以利用 ​​then()​​ 方法处理Promise对象状态为已兑现时的返回值,也可以使用 ​​catch()​​​ 方法来处理Promise对象状态为已拒绝时的错误信息。

myPromise.then(result => {console.log(result); // 打印: 操作成功}).catch(error => {console.error(error); // 打印错误信息});

当Promise对象状态为已兑现时,​​then()​​方法会调用传入的回调函数并输出成功的信息;当Promise对象状态为已拒绝时,则会调用​​catch()​​​方法中的回调函数输出错误信息。


二、使用 ​​fetch()​​ API

​fetch()​​ API 是一个现代的网络请求接口,广泛用于发起网络请求并处理响应。它返回一个 Promise,使得异步操作的管理变得更加简单和直观。​​fetch()​​​ 通常用于获取网络资源,如 RESTful API 的数据。

基本的 ​​fetch()​​ 使用

以下是使用 ​​fetch()​​ 发送 GET 请求并处理响应的基本示例:

fetch('https://api.example.com/data').then(response => {// 检查响应是否成功if (!response.ok) {throw new Error('网络响应失败');}return response.json(); // 解析 JSON 数据}).then(data => {console.log(data); // 输出返回的数据}).catch(error => {console.error('请求失败:', error); // 捕获并输出错误信息});
  • ​fetch()​​ 函数向指定的 URL 发送了 GET 请求。
  • 响应通过 ​​.then()​​ 方法处理。如果响应不正常(例如状态码不是 200-299),则会抛出一个错误。
  • 如果响应成功,使用 ​​response.json()​​ 方法解析 JSON 格式的数据,并在随后的 ​​.then()​​​ 中使用解析后的数据。

发送 POST 请求

除了发送 GET 请求外,​​fetch()​​​ 还可以用来发送 POST 请求。在发送 POST 请求时,可以传递一个包含请求体的配置对象。

fetch('https://api.example.com/data', {method: 'POST', // 指定请求方法为 POSTheaders: {'Content-Type': 'application/json' // 设置请求头部信息},body: JSON.stringify({ key: 'value' }) // 转换请求体为 JSON 字符串
})
.then(response => {// 检查响应状态if (!response.ok) {throw new Error('网络响应失败');}return response.json(); // 解析 JSON 数据
})
.then(data => {console.log(data); // 输出返回的数据
})
.catch(error => {console.error('请求失败:', error); // 捕获并输出错误信息
});
  • 使用 ​​method: 'POST'​​ 指明请求类型。
  • 设置请求头 ​​Content-Type​​ 为 ​​application/json​​,表明请求体的格式。
  • 使用 ​​body​​​ 属性将请求体转换为 JSON 字符串,以便于服务器理解。

三、链式使用 Promise

Promise 提供了链式调用的能力,这意味着可以在一个 ​​then()​​​ 处理程序中返回另一个 Promise,从而形成异步操作的链式结构。


链式调用

下面示例中,展示了如何使用 Promise 的链式调用来依次请求两个不同的数据资源:

fetch('https://api.example.com/data1').then(response => response.json()).then(data1 => {console.log('数据1:', data1);return fetch('https://api.example.com/data2'); // 返回另一个 Promise}).then(response => response.json()).then(data2 => {console.log('数据2:', data2);}).catch(error => {console.error('请求失败:', error);});
  • 第一个 ​​fetch()​​ 请求获取第一个数据资源,通过 ​​.then()​​ 解析响应为 JSON 数据。
  • 在第一个 ​​.then()​​ 处理程序中,我们输出第一个数据并返回另一个 ​​fetch()​​ 请求,以发起第二个异步操作。
  • 第二个 ​​fetch()​​ 请求获取第二个数据资源,通过 ​​.then()​​ 解析响应为 JSON 数据。
  • 最后一个 ​​.then()​​​ 处理程序输出第二个数据。

工作原理

当一个 Promise 被 ​​resolve​​ 时,它会传递给下一个 ​​.then()​​ 处理程序。如果在 ​​.then()​​​ 处理程序中返回一个新的 Promise,则当前 Promise 的状态将取决于此新 Promise 的状态。这样就形成了一条链,依次处理多个异步操作。


四、错误捕获

在使用 Promise 进行异步操作时,错误处理是非常重要的一部分。通过在 Promise 链中使用 ​​catch()​​​ 方法,可以捕获整个链中发生的错误,并进行相应的处理。

错误处理

示例中展示了如何在一个 Promise 链中处理错误:

fetch('https://api.example.com/data1').then(response => {if (!response.ok) {throw new Error('网络响应失败');}return response.json();}).then(data1 => {console.log('数据1:', data1);return fetch('https://api.example.com/data2');}).then(response => {if (!response.ok) {throw new Error('网络响应失败');}return response.json();}).then(data2 => {console.log('数据2:', data2);}).catch(error => {console.error('请求失败:', error);});
  • 每个 ​​.then()​​ 处理程序都会检查响应是否成功。如果不成功,则抛出一个 Error。
  • ​catch()​​ 方法用于捕获所有发生的错误,包括前面任何一个 Promise 的错误。
  • 如果任何一个 Promise 出现错误,后续的 ​​.then()​​ 处理程序会被跳过,直接执行 ​​catch()​​​ 中的错误处理逻辑。

Promise 链中的任何一个 Promise 的错误都会传递到最近的 ​​catch()​​ 方法中。这样做可以确保整个链中的任何一个步骤出现问题时都能得到正确的处理。​​catch()​​​ 方法也可以用来统一处理整个链中的错误,使代码更加清晰和易于维护。


五、Promise 术语

讨论 Promise 中了解一些重要的术语很有帮助。以下是一些常见的 Promise 术语及其含义:

  • Promise 实例: 通过 ​​new Promise()​​ 创建的对象,代表一个异步操作的最终完成或失败。
  • Executor 函数: Promise 构造函数中传递的函数,定义了异步操作的行为和状态变化。
  • then() 方法: 用于处理 Promise 对象的成功状态(fulfilled)的回调函数,接受一个成功的值作为参数。
  • catch() 方法: 用于处理 Promise 对象的失败状态(rejected)的回调函数,接受一个错误作为参数。
  • finally() 方法: 无论 Promise 的状态如何(成功或失败),都会执行的回调函数。

使用 ​​finally()​

下面的示例展示了如何使用 ​​finally()​​ 方法来进行清理工作,无论 Promise 是成功还是失败,​​finally()​​​ 中的回调都会被执行:

fetch('https://api.example.com/data').then(response => {if (!response.ok) {throw new Error('网络响应失败');}return response.json();}).then(data => {console.log(data);}).catch(error => {console.error('请求失败:', error);}).finally(() => {console.log('请求完成,无论成功或失败。');});
  • 如果获取数据成功,数据将会被输出到控制台。
  • 如果获取数据失败,错误信息将会被输出到控制台。
  • 无论前面的 Promise 是成功还是失败,​​finally()​​​ 中的回调都会被执行,用来进行一些清理工作或其他必要的操作。

六、合并多个 Promise

处理多个异步操作时,可以使用 Promise.all() 和 Promise.race() 这两种方法来组合多个 Promise 对象。

Promise.all()

Promise.all() 方法接收一个包含多个 Promise 的数组作为参数,只有当所有 Promise 都成功时,返回的 Promise 才会成功。如果其中任何一个 Promise 失败,则返回的 Promise 也会失败。

const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');Promise.all([promise1, promise2]).then(responses => {return Promise.all(responses.map(response => {if (!response.ok) {throw new Error('网络响应失败');}return response.json();}));}).then(data => {console.log('数据:', data);}).catch(error => {console.error('请求失败:', error);});
  • 通过 Promise.all() 组合了两个获取数据的 Promise。
  • 如果所有 Promise 都成功,我们会将获取的数据输出到控制台。
  • 如果任何一个 Promise 失败(例如网络响应失败),则捕获并输出错误信息。

Promise.race()

Promise.race() 方法返回一个 Promise,该 Promise 只会在第一个 Promise 解决或拒绝时解决。即使其他 Promise 还没有完成,只要有一个 Promise 在之前完成或失败,race() 返回的 Promise 就会立即解决。

const promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 100, '第一个 Promise 完成');
});
const promise2 = new Promise((resolve, reject) => {setTimeout(reject, 50, '第二个 Promise 失败');
});Promise.race([promise1, promise2]).then(result => {console.log(result); // 不会执行,因为 promise2 先失败}).catch(error => {console.error(error); // 输出: 第二个 Promise 失败});
  • 创建了两个延迟的 Promise,一个成功一个失败。
  • 使用 Promise.race() 来比较这两个 Promise,结果是第二个 Promise 失败,因此 catch() 方法被触发,输出失败的原因。

7. async 和 await

async 和 await 是 ES2017 引入,用于更简洁地处理 Promise。async 关键字用于定义异步函数,await 用于等待 Promise 解决。

使用 async 和 await

async function fetchData() {try {const response1 = await fetch('https://api.example.com/data1');if (!response1.ok) {throw new Error('网络响应失败');}const data1 = await response1.json();console.log('数据1:', data1);const response2 = await fetch('https://api.example.com/data2');if (!response2.ok) {throw new Error('网络响应失败');}const data2 = await response2.json();console.log('数据2:', data2);} catch (error) {console.error('请求失败:', error);}
}fetchData();
  • 使用 async 定义了一个异步函数 fetchData(),里面包含多个 await 表达式来等待 Promise 解决,并处理返回的数据。
  • 如果任何一个 Promise 解决失败,错误信息将被捕获并输出到控制台。

async 函数的返回值

async 函数总是返回一个 Promise,即使函数内没有显式返回值。下面的示例展示了这一点:

async function example() {return 'Hello, World!';
}example().then(message => {console.log(message); // 输出: Hello, World!
});
  • async 函数 example() 返回一个字符串 'Hello, World!'。
  • 虽然在函数内没有显式返回 Promise,但由于是 async 函数,最终返回的仍然是一个 Promise 对象。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=tfvwshelnu3w

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61011.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLO系列基础(六)YOLOv1原理详解,清晰明了!

系列文章地址 YOLO系列基础(一)卷积神经网络原理详解与基础层级结构说明-CSDN博客 YOLO系列基础(二)Bottleneck瓶颈层原理详解-CSDN博客 YOLO系列基础(三)从ResNet残差网络到C3层-CSDN博客 YOLO系列基础…

硬石电机学习2024116

F4 概况 共模抑制线圈作用是滤波 LD3.3是将5v转为芯片用的3.3V CH340用于板子和电脑通讯 光耦隔离保护主控 16M的外部flash 1M的芯片内部的flash 10kHZ高速的光耦隔离,1M的低俗光耦隔离 F4 stm32概况 stm8和51都是一次可以运算处理8位的 32表示一次处理32位…

基于Python爬虫大屏可视化的热门旅游景点数据分析系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

RAG经验论文《FACTS About Building Retrieval Augmented Generation-based Chatbots》笔记

《FACTS About Building Retrieval Augmented Generation-based Chatbots》是2024年7月英伟达的团队发表的基于RAG的聊天机器人构建的文章。 这篇论文在待读列表很长时间了,一直没有读,看题目以为FACTS是总结的一些事实经验,阅读过才发现FAC…

解析传统及深度学习目标检测方法的原理与具体应用之道

深度学习目标检测算法 常用的深度学习的目标检测算法及其原理和具体应用方法: R-CNN(Region-based Convolutional Neural Networks)系列1: 原理: 候选区域生成:R-CNN 首先使用传统的方法(如 Se…

boost之property

简介 property在boost.graph中有使用,用于表示点属性或者边属性 结构 #mermaid-svg-56YI0wFLPH0wixrJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-56YI0wFLPH0wixrJ .error-icon{fill:#552222;}#me…

Oracle 19c PDB克隆后出现Warning: PDB altered with errors受限模式处理

在进行一次19c PDB克隆过程中,发现克隆结束,在打开后出现了报错,PDB变成受限模式,以下是分析处理过程 09:25:48 SQL> alter pluggable database test1113 open instancesall; Warning: PDB altered with errors. Elapsed: 0…

AndroidStudio-Activity的生命周期

一、Avtivity的启动和结束 从当前页面跳到新页面,跳转代码如下: startActivity(new Intent(源页面.this,目标页面.class)); 从当前页面回到上一个页面,相当于关闭当前页面,返回代码如下: finis…

ubuntu20.04 解决Pycharm没有写入权限,无法通过检查更新更新的问题

ubuntu20.04 解决Pycharm没有写入权限,无法通过检查更新更新的问题 您提供的截图显示了一个关于PyCharm更新的问题,其中提到了:“PyCharm 没有 /opt/pycharm-community-2024.1.2 的写入权限,请通过特权用户运行以更新。” 这表明…

云原生之运维监控实践-使用Telegraf、Prometheus与Grafana实现对InfluxDB服务的监测

背景 如果你要为应用程序构建规范或用户故事,那么务必先把应用程序每个组件的监控指标考虑进来,千万不要等到项目结束或部署之前再做这件事情。——《Prometheus监控实战》 去年写了一篇在Docker环境下部署若依微服务ruoyi-cloud项目的文章,当…

WinDefender Weaker

PPL Windows Vista / Server 2008引入 了受保护进程的概念,其目的不是保护您的数据或凭据。其最初目标是保护媒体内容并符合DRM (数字版权管理)要求。Microsoft开发了此机制,以便您的媒体播放器可以读取例如蓝光,同时…

计算机视觉 1-8章 (硕士)

文章目录 零、前言1.先行课程:python、深度学习、数字图像处理2.查文献3.环境安装 第一章:概论1.计算机视觉的概念2.机器学习 第二章:图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示:图像金字…

实习冲刺练习 第二十三天

每日一题 回文链表. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool isPalindrome(ListNode* head) {if(headnullptr) return false;vector<int> v;while(head!nullptr){//将链表的值存入数组中v.push_back(head->val);headhead->next;}in…

报错 No available slot found for the embedding model

报错内容 Server error: 503 - [address0.0.0.0:12781, pid304366] No available slot found for the embedding model. We recommend to launch the embedding model first, and then launch the LLM models. 目前GPU占用情况如下 解决办法: 关闭大模型, 先把 embedding mode…

RabbitMQ介绍和快速上手案例

文章目录 1.引入1.1同步和异步1.2消息队列的作用1.3rabbitMQ介绍 2.安装教程2.1更新软件包2.2安装erlang2.3查看这个erlang版本2.4安装rabbitMQ2.5安装管理页面2.6浏览器测试2.7添加管理员用户 3.rabbitMQ工作流程4.核心概念介绍4.1信道和连接4.2virtual host4.3quene队列 5.We…

数据结构(初阶4)---循环队列详解

循环队列 1.循环队列的结构  1).逻辑模式 2.实现接口  1).初始化  2).判断空和满  3).增加  4).删除  5).找头  6).找尾 3.循环队列的特点 1.循环队列的结构 1).逻辑模式 与队列是大同小异的&#xff0c; 其中还是有一个指向队列头的head指针&#xff0c; 也有一个指向尾…

java中volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗?

大家好&#xff0c;我是锋哥。今天分享关于【java中volatile 类型变量提供什么保证&#xff1f;能使得一个非原子操作变成原子操作吗&#xff1f;】面试题。希望对大家有帮助&#xff1b; java中volatile 类型变量提供什么保证&#xff1f;能使得一个非原子操作变成原子操作吗&…

Python - 初识Python;Python解释器下载安装;Python IDE(一)

一、初识Python Python 是一种高级编程语言&#xff0c;Python是一种面向对象的解释型计算机程序设计语言&#xff0c;Python由荷兰国家数学与计算机科学研究中心的吉多范罗苏姆&#xff08;&#xff09;Guido van Rossum吉多范罗苏姆&#xff08;&#xff09;于1989 年底发明…

AR眼镜方案_AR智能眼镜阵列/衍射光波导显示方案

在当今AR智能眼镜的发展中&#xff0c;显示和光学组件成为了技术攻坚的主要领域。由于这些组件的高制造难度和成本&#xff0c;其光学显示模块在整个设备的成本中约占40%。 采用光波导技术的AR眼镜显示方案&#xff0c;核心结构通常由光机、波导和耦合器组成。光机内的微型显示…