Promise的用法及案列

Promise:异步编程的优雅解决方案

在JavaScript中,异步编程是处理耗时操作(如网络请求、文件读取等)的重要手段。传统的异步编程方式(如回调函数)往往会导致“回调地狱”问题,使得代码结构混乱、难以维护。为了解决这一问题,ES6引入了Promise对象,提供了一种更加优雅、可读性更高的异步编程模式。

一、Promise的基本概念

Promise是一个构造函数,用于创建表示异步操作的对象。Promise对象有三种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败)。当Promise被创建时,它处于Pending状态。通过调用resolve方法,可以将Promise的状态更改为Resolved,并传递一个结果值;通过调用reject方法,可以将Promise的状态更改为Rejected,并传递一个错误信息。

二、Promise的用法

  1. 创建Promise对象

    使用new Promise(executor)语法创建Promise对象,其中executor是一个接受两个参数的函数:resolvereject。这两个参数也是函数,分别用于将Promise的状态更改为Resolved和Rejected。

    const promise = new Promise((resolve, reject) => {// 异步操作if (/* 操作成功 */) {resolve('成功的结果');} else {reject('失败的原因');}
    });
    
  2. 处理Promise结果

    Promise对象提供了thencatch方法,用于处理成功和失败的情况。then方法接受两个参数:onFulfilled(成功时的回调函数)和onRejected(失败时的回调函数)。catch方法用于捕获Promise链中的错误。

    promise.then((value) => {console.log('成功:', value);},(reason) => {console.error('失败:', reason);}
    ).catch((error) => {console.error('捕获到的错误:', error);
    });
    
  3. Promise链式调用

    Promise支持链式调用,即一个Promise对象的then方法可以返回一个新的Promise对象,从而可以继续调用then方法。这允许我们将多个异步操作串联起来,形成一个清晰的异步流程。

    const firstPromise = new Promise((resolve) => {setTimeout(() => resolve('第一个操作成功'), 1000);
    });const secondPromise = firstPromise.then((value) => {console.log(value);return new Promise((resolve) => {setTimeout(() => resolve('第二个操作成功'), 1000);});
    });secondPromise.then((value) => {console.log(value);
    });
    
  4. Promise静态方法

    Promise还提供了几个静态方法,用于创建和处理Promise对象:

    • Promise.all(iterable):接受一个可迭代对象(如数组),返回一个新的Promise对象,该对象在所有给定的Promise对象都成功时才会成功,任何一个失败都会导致整个Promise对象失败。
    • Promise.race(iterable):接受一个可迭代对象,返回一个新的Promise对象,该对象的状态由第一个完成的Promise对象决定(无论是成功还是失败)。
    • Promise.resolve(value):返回一个以给定值解析的Promise对象。
    • Promise.reject(reason):返回一个以给定原因拒绝的Promise对象。

三、Promise的创作流程

  1. 定义Promise构造函数

    创建一个类(或构造函数),用于生成Promise对象。在该构造函数中,定义状态(Pending、Resolved、Rejected)和存储结果或错误信息的变量。同时,定义resolvereject方法,用于更改状态和存储结果或错误信息。

    class MyPromise {constructor(fn) {this._status = 'pending';this._value = undefined;const resolve = (value) => {if (this._status === 'pending') {this._status = 'fulfilled';this._value = value;}};const reject = (reason) => {if (this._status === 'pending') {this._status = 'rejected';this._value = reason;}};try {fn(resolve, reject);} catch (error) {reject(error);}}then(onFulfilled, onRejected) {if (this._status === 'fulfilled' && onFulfilled) {onFulfilled(this._value);}if (this._status === 'rejected' && onRejected) {onRejected(this._value);}}
    }
    
  2. 实现then方法

    在Promise类中实现then方法,该方法接受两个参数:成功时的回调函数和失败时的回调函数。根据Promise的当前状态,调用相应的回调函数,并传递结果或错误信息。

    // 在MyPromise类中实现的then方法(见上)
    
  3. 使用Promise对象

    使用new MyPromise(executor)语法创建MyPromise对象,并在executor函数中执行异步操作。通过调用then方法处理成功和失败的情况。

    const myPromise = new MyPromise((resolve, reject) => {setTimeout(() => {const success = true; // 模拟异步操作的成功或失败if (success) {resolve('异步操作成功');} else {reject('异步操作失败');}}, 1000);
    });myPromise.then((value) => {console.log('成功:', value);},(reason) => {console.error('失败:', reason);}
    );
    

以下是一些关于Promise的实际案例,涵盖了JavaScript中Promise的不同使用场景:

四、基本使用案例

  1. 异步请求的链式处理

    • 场景描述:在处理网络请求时,经常需要按照特定的顺序执行多个异步操作。
    • 示例代码:
    function fetchData(url) {return new Promise((resolve, reject) => {// 模拟网络请求setTimeout(() => {resolve("数据加载完成");// 或者 reject("请求失败");}, 1000);});
    }fetchData("http://example.com/data").then(response => {console.log(response);return fetchData("http://example.com/more-data");}).then(moreResponse => {console.log(moreResponse);}).catch(error => {console.error("请求出错:", error);});
    
  2. 文件读取

    • 场景描述:在Node.js环境中,读取文件是一个常见的异步操作。
    • 示例代码(假设使用fs模块):
    const fs = require('fs').promises;fs.readFile('example.txt', 'utf-8').then(data => {console.log("文件内容:", data);}).catch(error => {console.error("读取文件出错:", error);});
    

五、高级使用案例

  1. Promise.race实现请求超时处理

    • 场景描述:在发送请求时,如果请求在一定时间内没有响应,则视为请求超时。
    • 示例代码:
    const p1 = fetchData("http://example.com/slow-data");
    const p2 = new Promise((_, reject) => {setTimeout(() => reject(new Error("请求超时")), 3000);
    });Promise.race([p1, p2]).then(response => {console.log(response);}).catch(error => {console.error("请求出错或超时:", error);});
    
  2. Promise.all用于并行处理多个请求

    • 场景描述:有时需要同时发送多个请求,并等待所有请求都完成后才进行下一步操作。
    • 示例代码:
    const requests = [fetchData("http://example.com/data1"),fetchData("http://example.com/data2"),fetchData("http://example.com/data3")
    ];Promise.all(requests).then(responses => {responses.forEach(response => {console.log(response);});}).catch(error => {console.error("其中一个请求出错:", error);});
    
  3. Promise的重试机制

    • 场景描述:在某些情况下,如果请求失败,可能需要进行重试。
    • 示例代码:
    function retryFetchData(url, times = 3, delay = 1000) {return new Promise((resolve, reject) => {function attempt() {fetchData(url).then(resolve).catch(error => {if (times > 1) {console.log(`还有${times - 1}次尝试`);setTimeout(attempt, delay);} else {reject(error);}});}attempt();});
    }retryFetchData("http://example.com/unreliable-data").then(response => {console.log(response);}).catch(error => {console.error("请求失败,重试后仍然出错:", error);});
    

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

国内超声波清洗机哪个品牌好?力荐四款超耐用超声波清洗机!

超声波清洗机作为一款高效实用的家庭与专业清洁利器,能够迅速且彻底地清洁多样化的物件。面对市场上琳琅满目的品牌与型号,每一款都各具特色与优势,故在决定购买前做足调研显得尤为重要,以免购入不尽如人意的产品,造成…

力扣110:判断二叉树是否为平衡二叉树

利用二叉树遍历的思想编写一个判断二叉树,是否为平衡二叉树 示例 : 输入:root [3,9,20,null,null,15,7] 输出:true思想: 代码: int getDepth(struct TreeNode* node) {//如果结点不存在,返回…

打造自己的RAG解析大模型:Windows部署OCR服务(可商业应用)

在上一篇文章中,我们介绍了如何在 Windows 环境中配置 OCR 相关模型,并完成了模型验证。本篇文章将基于之前的内容,进一步讲解如何将文本检测、方向分类和文本识别模型进行串联,最终搭建一个基础的 OCR 应用服务。通过这些模型的串…

【Diffusion分割】CTS:基于一致性的医学图像分割模型

CTS: A Consistency-Based Medical Image Segmentation Model 摘要: 在医学图像分割任务中,扩散模型已显示出巨大的潜力。然而,主流的扩散模型存在采样次数多、预测结果慢等缺点。最近,作为独立生成网络的一致性模型解决了这一问…

回调函数是什么

回调函数是什么 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。 回调函数不是由该函数的实现⽅直接调⽤&…

Linux驱动开发(速记版)--GPIO子系统

第105章 GPIO 入门 105.1 GPIO 引脚分布 RK3568 有 5 组 GPIO:GPIO0 到 GPIO4。 每组 GPIO 又以 A0 到 A7,B0 到 B7,C0 到C7,D0 到 D7,作为区分的编号。 所以 RK3568 上的 GPIO 是不是应该有 5*4*8160 个呢&#xff1…

Semantic Communication Meets Edge Intelligence——构造终端共享的知识图谱指导无线物联网通信中文本的传输

论文链接: IEEE Xplore Full-Text PDF:https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9979702 1. 背景 随着自动驾驶、智能城市等应用的发展,移动数据流量将大幅增加。传统的香农信息论(CIT)通信系统已接近其带…

SpringBoot MyBatis连接数据库设置了encoding=utf-8还是不能用中文来查询

properties的MySQL连接时已经指定了字符编码格式&#xff1a; url: jdbc:mysql://localhost:3306/sky_take_out?useUnicodetrue&characterEncodingutf-8使用MyBatis查询&#xff0c;带有中文参数&#xff0c;查询出的内容为空。 执行的语句为&#xff1a; <select id&…

decltype推导规则

decltype推导规则 当用decltype(e)来获取类型时&#xff0c;编译器将依序判断以下四规则&#xff1a; 1.如果e是一个没有带括号的标记符表达式(id-expression)或者类成员访问表达式&#xff0c;那么decltype(e)就是e所命名的实体的类型。此外&#xff0c;如果e是一个被重载的函…

k8s 中存储之 NFS 卷

目录 1 NFS 卷的介绍 2 NFS 卷的实践操作 2.1 部署一台 NFS 共享主机 2.2 在所有k8s节点中安装nfs-utils 2.3 部署nfs卷 2.3.1 生成 pod 清单文件 2.3.2 修改 pod 清单文件增加 实现 NFS卷 挂载的 参数 2.3.3 声明签单文件并查看是否创建成功 2.3.4 在 NFS 服务器 创建默认发布…

思维导图工具,轻松搞定复杂问题!

一提到思维导图&#xff0c;想必大家都不会陌生&#xff1b;它能帮助我们更好地梳理思路&#xff0c;让复杂的想法变得清晰可见&#xff1b;而随着互联网的普及&#xff0c;在线思维导图工具更是成为了我们日常工作和学习的得力助手&#xff1b;今天&#xff0c;我就来给大家推…

小红书算法岗面试,竞争太激烈了

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

【Kubernetes】常见面试题汇总(五十八)

目录 127.创建 PV 失败&#xff1f; 128. pod 无法挂载 PVC&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 69-113 属于【Kubernetes】…

一个月学会Java 第4天 运算符和数据转换

Day4 运算符和数据转换 今天来讲运算符&#xff0c;每个运算符的作用和现象&#xff0c;首先我们先复习一下数据类型&#xff0c; day2讲过基本数据类型有八种&#xff0c;int、short、long、byte、char、boolean、float、double&#xff0c;分别为四个整型、一个字符型、一个布…

基于springboot vue3 在线考试系统设计与实现 源码数据库 文档

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆…

电脑断网或者经常断网怎么办?

1、首先&#xff0c;按一下键盘的win R &#xff0c; 在打开的运行框内输入&#xff1a;cmd 然后按一下回车 或者 点击一下【确定】 2、在命令窗口输入&#xff1a;ipconfig/release , 然后按一下回车 作用&#xff1a;IP释放&#xff0c;相当于把网线拔了重新插上 3、接着…

佳能基于SPAD的监控摄像机MS-500入选《时代》2023最佳发明

一、产品概述 佳能MS-500是一款采用SPAD(Single Photon Avalanche Diode,单光子雪崩二极管)传感器的监控摄像机。SPAD传感器以其极高的灵敏度和在低光环境下的卓越表现而闻名,使得MS-500能够在夜晚或极暗光条件下拍摄到清晰、彩色的画面。此外,MS-500还配置了高性能的镜头…

Python异常处理中的9个常见错误及其解决办法,建议收藏

在Python编程中&#xff0c;异常处理是确保程序健壮性和可靠性的重要部分。然而&#xff0c;在使用异常处理时&#xff0c;开发者可能会犯一些常见的错误。以下是9个常见的异常处理错误及其解决办法&#xff1a; 1. 语法错误 (SyntaxError) 语法错误是最常见的错误之一。它通…

【梯级水电站调度优化】基于线性递减策略优化粒子群算法

课题名称&#xff1a; 基于改进粒子群算法的梯级水电站调度优化 改进方向&#xff1a; 线性递减策略优化粒子群PSO 代码获取方式&#xff08;付费&#xff09;&#xff1a; 相关资料&#xff1a; 1. 粒子群算法的基本原理 2. 梯级水电站调度优化模型 3. 代码注释 4. 代码…

第十一章 缓存之更新/穿透/雪崩/击穿

目录 一、什么是缓存 二、缓存更新策略 2.1. 缓存主动更新策略 2.1.1. Cache Aside模式&#xff08;主流&#xff09;‌ 2.1.2. Read/Write Through模式‌ 2.1‌.3. Write Behind模式‌ 2.1.4. 总结 三、缓存穿透 四、缓存雪崩 五、缓存击穿 本文中的图片内容部分来源…