AJAX-Promise 详解

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

目录

前言

一、Promise基本概念

1.1 定义

1.2 状态

1.3 构造函数

二、Promise基本用法

2.1 then()

2.2 catch()

2.3 链式调用

三、Promise高级特性

3.1 Promise.all()

3.2 Promise.allSettled()

3.3 Promise.race()

3.4Promise.any()

四. Promise的调试与优化

4.1 使用async/await

4.2 错误处理

4.3 并行执行

4.4 性能优化

五. 结论


前言

在JavaScript的异步编程世界中,Promise无疑是一个里程碑式的存在。它提供了一种更加优雅和强大的方式来处理异步操作,解决了传统回调函数的“回调地狱”问题,使得代码更加清晰、易于维护。本文将深入探索Promise的各个方面,包括其基本概念、基本用法、链式调用、错误处理、静态方法、与async/await的结合使用,以及在实际项目中的应用。

一、Promise基本概念

1.1 定义

Promise是JavaScript中的一个对象,它代表了一个尚未完成但预期将来会完成的异步操作的结果。它允许你为异步操作的成功(fulfilled)和失败(rejected)注册回调函数。

1.2 状态

Promise有三种状态:

  • Pending(等待中):初始状态,既不是成功,也不是失败状态。
  • Fulfilled(已成功):意味着操作成功完成。
  • Rejected(已失败):意味着操作失败。

一旦Promise被fulfilled或rejected,它的状态就不能再改变。

1.3 构造函数

Promise的构造函数接收一个执行器(executor)函数作为参数,该执行器函数本身又接收两个函数作为参数:resolve和reject。

let promise = new Promise(function(resolve, reject) {  // 异步操作  if (/* 异步操作成功 */) {  resolve(value); // 将Promise的状态从"pending"变为"fulfilled",并将value作为操作成功的结果  } else {  reject(error); // 将Promise的状态从"pending"变为"rejected",并将error作为操作失败的原因  }  
});

二、Promise基本用法

2.1 then()

then()方法用于指定Promise成功时(即fulfilled时)的回调函数,并返回一个新的Promise实例。

promise.then(function(value) {  // 当Promise成功时执行  console.log(value);  
}, function(error) {  // 可选:当Promise失败时执行(但通常不推荐这种方式,因为会破坏链式调用)  console.error(error);  
});

2.2 catch()

catch()方法是.then(null, rejection)的语法糖,用于指定Promise失败时(即rejected时)的回调函数。

promise.then(function(value) {  // 成功时执行  
}).catch(function(error) {  // 失败时执行  console.error(error);  
});

2.3 链式调用

Promise支持链式调用,因为then()catch()方法都会返回一个新的Promise实例。

fetch('https://api.example.com/data')  .then(response => response.json())  .then(data => {  console.log(data);  })  .catch(error => {  console.error('Fetch error:', error);  });

三、Promise高级特性

3.1 Promise.all()

Promise.all()方法接收一个Promise对象的数组作为参数,并返回一个新的Promise实例。只有当数组中的所有Promise都被fulfilled时,返回的Promise才会被fulfilled,其结果是一个包含所有fulfilled值的数组。

let promise1 = Promise.resolve(3);  
let promise2 = 42;  
let promise3 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo'));  Promise.all([promise1, promise2, promise3]).then(values => {  console.log(values); // [3, 42, "foo"]  
});

3.2 Promise.allSettled()

Promise.allSettled()是ES2020中引入的一个新方法,它类似于Promise.all(),但不同之处在于它等待所有给定的Promise都完成(无论是fulfilled还是rejected),并返回一个数组,数组中的每个元素都是一个对象,描述了对应Promise的结果。

const promise1 = Promise.resolve(3);  
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 50, 'rejection'));  
const promise3 = new Promise((resolve) => setTimeout(resolve, 100, 'foo'));  Promise.allSettled([promise1, promise2, promise3]).then((results) => {  results.forEach((result) => {  if (result.status === 'fulfilled') {  console.log('fulfilled:', result.value);  } else if (result.status === 'rejected') {  console.log('rejected:', result.reason);  }  });  // 输出:  // fulfilled: 3  // rejected: rejection  // fulfilled: foo  
});

3.3 Promise.race()

Promise.race()方法返回一个新的Promise,该Promise以输入数组中第一个解决(无论是fulfilled还是rejected)的Promise的结果作为自己的结果。这在处理具有超时限制或需要快速响应的场景时非常有用。

const fastPromise = new Promise((resolve) => setTimeout(resolve, 100, 'Fast one won'));  
const slowPromise = new Promise((resolve) => setTimeout(resolve, 500, 'But I am here too'));  Promise.race([fastPromise, slowPromise]).then((value) => {  console.log(value); // 输出: Fast one won  
}).catch((error) => {  console.error('An error occurred', error);  
});

3.4Promise.any()

Promise.any()是ES2020中引入的另一个静态方法,它返回一个新的Promise,该Promise以输入数组中第一个成功(fulfilled)的Promise的结果作为自己的结果。如果所有输入的Promise都失败了,则返回的Promise将拒绝(reject),并抛出一个AggregateError,表示所有Promise都失败了。

const promise1 = new Promise((resolve, reject) => setTimeout(reject, 500, 'First failed'));  
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'Second succeeded'));  
const promise3 = new Promise((resolve, reject) => setTimeout(reject, 150, 'Third failed'));  Promise.any([promise1, promise2, promise3]).then((value) => {  console.log(value); // 输出: Second succeeded  
}).catch((errors) => {  console.error('All promises failed', errors);  // 在这个例子中,这个catch块不会被执行  
});

四. Promise的调试与优化

在使用Promise进行异步编程时,合理的调试和优化是提高代码质量和性能的关键。以下是一些建议:

  • 使用浏览器的开发者工具:利用浏览器的网络监控、断点调试等功能来跟踪Promise的状态和值。
  • 避免创建不必要的Promise链:保持Promise链的简洁性,避免过长的链式调用,以减少回调地狱(Callback Hell)的发生。
  • 利用async/await简化异步代码async/await是JavaScript中处理异步操作的现代、更简洁的语法糖,它们基于Promise构建,可以让异步代码看起来和同步代码一样。以下是如何利用async/await来进一步简化和优化Promise的使用。

4.1 使用async/await

async关键字用于声明一个异步函数,该函数会隐式地返回一个Promise。在async函数内部,你可以使用await关键字来等待一个Promise解决,而无需显式地编写.then().catch()链。

async function fetchData() {  try {  const response = await fetch('https://api.example.com/data');  const data = await response.json();  console.log(data);  } catch (error) {  console.error('Failed to fetch data:', error);  }  
}  fetchData();

在这个例子中,fetchData函数是异步的,它使用await来等待fetch调用和JSON解析的结果。如果任何一个await表达式失败,控制流将跳转到catch块。

4.2 错误处理

在使用async/await时,错误处理变得非常直观。你可以使用标准的try...catch语句来捕获和处理异步操作中发生的错误。

async function fetchAndProcessData() {  try {  const data = await fetchData(); // 假设fetchData是一个返回Promise的异步函数  // 处理数据  } catch (error) {  console.error('Error processing data:', error);  }  
}

4.3 并行执行

虽然async/await使代码看起来像是同步的,但你不应该用它来并行执行多个异步操作。对于这种情况,你应该使用Promise.all()或其他并行执行的方法,然后在async函数中使用await等待所有操作完成。

async function fetchMultipleData() {  const promises = [  fetch('https://api.example.com/data1'),  fetch('https://api.example.com/data2')  ];  const [response1, response2] = await Promise.all(promises);  const [data1, data2] = await Promise.all([response1.json(), response2.json()]);  console.log(data1, data2);  
}  fetchMultipleData();

4.4 性能优化

  • 避免不必要的等待:不要在没有必要时使用await,特别是在循环或频繁调用的函数中。
  • 使用缓存:对于重复请求相同资源的情况,考虑使用缓存来避免不必要的网络请求。
  • 限制并发请求:如果你的应用需要发送大量并发请求,考虑限制同时进行的请求数量,以避免资源耗尽。

五. 结论

Promise是JavaScript中处理异步操作的重要工具,而async/await则为它们的使用提供了更简洁、更直观的语法。通过合理使用Promise的高级特性和async/await,你可以编写出既清晰又高效的异步代码。然而,重要的是要记住,异步编程的本质并未改变,只是工具和语法变得更加方便和强大。因此,理解和掌握异步编程的基本概念仍然是至关重要的。

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

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

相关文章

keras的路透社数据训练对测试数据的概率总和计算问题

在使用keras内置数据路透社新闻分类的时候,使用训练的模型预测测试数据。然后发现对预测数据分类的概率总和不是1. pridiction model.predict(x_test)for i in range(0,46):print(np.sum(pridiction[i]))然而python深度学习这本书里面的是1.0 问题目前没有解决。…

醒醒,别睡了...讲《数据分析pandas库》了—/—<3>

直接上知识点 一、 1、新建数据框时建立索引 所有的数据框默认都已经使用从 0 开始的自然数索引,因此这里的"建立”索引指的是自定 df pd.DataFrame( {varl : 1.0, var2 :[1,2,3,4], var3 :[test,python,test,hello] , var4 : cons} , index [0,1,2,3]) …

量化私募公司的多因子构建方案(附python代码)

原创文章第600篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 昨天代码已经发布了,大家可以前往下载和更新: 代码发布:quantlabv5.3,可转债所有数据及双低、动量因子策略,单因子分析框…

文件夹怎么设置密码?文件夹加密方法盘点

文件夹是电脑管理数据的重要工具,当我们将重要数据存储在文件夹中时,需要严格保护文件夹的数据安全,避免数据泄露。下面我们就来了解一下文件夹设置密码的方法。 文件夹加密 文件夹加密是指通过加密算法来加密保护文件夹,避免其他…

高级网页爬虫开发:Scrapy和BeautifulSoup的深度整合

引言 在互联网时代,数据的价值日益凸显。网页爬虫作为一种自动化获取网页内容的工具,广泛应用于数据挖掘、市场分析、内容聚合等领域。Scrapy是一个强大的网页爬虫框架,而BeautifulSoup则是一个灵活的HTML和XML文档解析库。本文将探讨如何将…

Kolla-Ansible的确是不支持CentOS-Stream系列产品了

看着OpenStack最新的 C 版本出来一段时间了,想尝个鲜、用Kolla-Ansible进行容器化部署,结果嘛。。。 根据实验结果,自OpenStack Bobcat版本开始,Kolla-Ansible就适合在CentOS系列产品上部署了,通过对 Bobcat和Caracal…

【docker】部署证书过期监控系统mouday/domain-admin

证书过期了再去部署证书容易被骂,就找了一个开源的证书过期系统来部署一下 过程 官方文档:https://domain-admin.readthedocs.io/zh-cn/latest/manual/install.html#docker 直接下载镜像是超时的,切换一下文档推荐的镜像源 新建docker配置…

模拟电子技术-实验四 二极管电路仿真

实验四 二极管电路仿真 一.实验类型 验证性实验 二.实验目的 1、验证二极管的单向导电性 2、验证二极管的稳压特性。 三.实验原理 二极管的单向导电性: 四、实验内容 1、二极管参数测试仿真实验 1)仪表仿真…

IndexError: index 0 is out of bounds for axis 1 with size 0

IndexError: index 0 is out of bounds for axis 1 with size 0 目录 IndexError: index 0 is out of bounds for axis 1 with size 0 【常见模块错误】 【解决方案】 欢迎来到我的主页,我是博主英杰,211科班出身,就职于医疗科技公司&#…

物联网主机 E6000:智慧应急领域的创新力量

在当今瞬息万变的世界中,突发事件和紧急情况时有发生。如何迅速、准确地应对这些挑战,保障人民生命财产安全,成为了社会发展的重要课题。而物联网主机 E6000 的出现,为智慧应急领域带来了全新的解决方案。 一、强大的性能与功能 物…

ueditor跨域问题解决

ueditor解决跨域问题 问题:1.在引用vue-ueditor-wrap后,上传图片和附件出现跨域问题,前端引用了webpack去解决跨域问题,但仍然存在跨域问题? ueditor是百度的富文本,功能较多但资料不够全,因为…

模拟string(四)详解

目录 判断string大小关系bool operator(const string&s1,const string s2)代码 bool operator<(const string& s1, const string& s2)代码 bool operator<(const string& s1, const string& s2)代码 bool operator>(const string& s1, const …

算法板子:使用数组模拟队列——在队尾插入元素、在队头弹出元素、判断队列是否为空、查询队头元素

使用数组模拟时长这个样子&#xff1a; 代码&#xff1a; #include <iostream> using namespace std;const int N 1e5 10;// 数组q相当于队列; // hh是队头指针&#xff0c;始终指向队头 // tt是队尾指针&#xff0c;始终指向队尾 int q[N], hh, tt -1;// 队尾插入元…

代码随想录算法训练营第 25 天 | LeetCode491.递增子序列 LeetCode46.全排列 LeetCode47.全排列ii

代码随想录算法训练营 Day25代码随想录算法训练营第 25 天 | LeetCode491.递增子序列 LeetCode46.全排列 LeetCode47.全排列ii 目录 代码随想录算法训练营前言LeetCode491.递增子序列LeetCode46.全排列LeetCode47.全排列ii 一、LeetCode491.递增子序列1.题目链接2.思路3.题解 …

【算法】单向环形链表解决Josephu(约瑟夫)问题

应用场景 n 个小孩标号&#xff0c;逆时针站一圈。从 k 号开始&#xff0c;每一次从当前的小孩逆时针数 m 个&#xff0c;然后让最后这个小孩出列。不断循环上述过程&#xff0c;直到所有小孩出列&#xff0c;由此产生出一个队列编号。 提示 用一个不带头节点的循环链表来处…

FPGA开发——状态机的使用

一、概述 我们在使用FPGA进行开发的过程当中&#xff0c;实现一个东西用得最多的实现方法就是状态机的实现方法&#xff0c;用一句话总结就是万物皆可状态机&#xff0c;这和我们在学习Linux时常说的在Linux中万物都是文件差不多&#xff0c;这里就主要就是突出状态机的应用范…

技术实践—微前端技术应用

微前端是一种新兴的前端架构模式&#xff0c;是一种类似于微服务的架构&#xff0c;将微服务的理念应用于浏览器端。其核心理念是将一个大而单一的前端应用拆分为多个小型独立的微应用。这些微应用各自独立&#xff0c;可以由不同团队开发维护&#xff0c;部署&#xff0c;组合…

【调色板软件】免费、开源的调色板软件,焰火十二卷,提供了多种功能来生成一组调和色彩NO.108

本文一共:316 个字,需要阅读:1 分钟,更新时间:2024年7 月27日,部分内容具有时效性,如有失效请留言,阅读量:0 使用平台&#xff1a; Windows/macOS/CentOS/Ubuntu 由于我不是很懂&#xff0c;有需要的人自己摸索吧 资源来源于网络&#xff0c;免费分享仅供学习和测试使用&…

PostgreSQL 中如何重置序列值:将自增 ID 设定为特定值开始

我是从excel中将数据导入&#xff0c;然后再通过sql插入数据&#xff0c;就报错。 需要设置自增ID开始值 1、确定序列名称&#xff1a; 首先&#xff0c;需要找到与的增字段相关的序列名称。假设表名是 my_table 和自增字段是 id&#xff0c;可以使用以下查询来获取序列名称…

C 语言动态链表

线性结构->顺序存储->动态链表 一、理论部分 从起源中理解事物&#xff0c;就是从本质上理解事物。 -杜勒鲁奇 动态链表是通过结点&#xff08;Node&#xff09;的集合来非连续地存储数据&#xff0c;结点之间通过指针相互连接。 动态链表本身就是一种动态分配内存的…