ES6--》一文搞懂JS中的Promise

news/2024/5/17 19:04:19/文章来源:https://blog.csdn.net/qq_53123067/article/details/127087102

目录

Promise

Promise使用

Promise封装Ajax请求

Promise封装读取文件

Promise.prototype.then 方法

Promise多文件读取

Promise.prototype.catch()

Promise.prototype.finally()

Promise.all()

Promise.race()

Promise.allSettled()

Pomise.any()

Promise.resolve()


Promise

Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

Promise特点

Promsie对象异步操作有三种状态,pending(进行中)、fulfilled(已成功)和reject(已失败)。只有异步操作才可以决定当前是哪种状态Promise状态改变有两种可能,从pending变为fulfidded和从pending变为rejected。状态发生改变就不能再改变了,称为:resolved(已定型)

Promise对象的作用:将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数,而且Promise提供了统一的接口,使得控制异步操作更加容易。

Promise使用

Promise构造函数接收一个函数作为参数,该函数的两个参数分别为:resolve 和 reject。

resolve:在异步操作成功时调用,并将异步操作的结果作为参数传递出去。

reject:在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。

Promise实例生成后,可以用 then 方法分别指定 resolved 状态和 rejected 状态的回调函数;而第一个回调函数是 Promise 对象状态变 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。案例如下:

<script>// 实例化 Promise 对象,接收参数为函数类型值const p = new Promise(function(resolve,reject){// 封装异步操作setTimeout(function(){// 数据操作// let data = '用户数据'// resolve// resolve(data)let err = '数据读取失败'reject(err)},1000)})// 调用 Promise 对象的 then 方法// 数据调用成功,则调用下面第一个回调,失败则是第二个p.then(function(value){//成功的形参console.log(value);},function(reason){//失败的形参console.log(reason);})
</script>

Promise新建后会立即执行,然而 then 方法指定的回调函数将在当前脚本所有同步任务执行完才会执行。

<script>let p = new Promise(function(resolve,reject){console.log('People');// 数据操作let data = 'World'resolve(data)})p.then(function(value){console.log(value);})console.log('Hello');
</script>

Promise封装Ajax请求

<script>const p = new Promise((resolve,reject) =>{// 1.创建对象const xhr = new XMLHttpRequest()// 2.初始化xhr.open("GET","https://ai.baidu.com/")// 3.发送xhr.send()// 4.绑定事件,处理响应结果xhr.onreadystatechange = function(){// 判断if(xhr.readyState ===4 ){// 判断响应码 200-299if(xhr.status >= 200 && xhr.status <300){// 表示成功resolve(xhr.response);}else{// 如果失败reject(xhr.status);}}}})// 指定成功和失败的回调p.then(function(value){console.log(value);},function(reason){console.error(reason);})
</script>

Promise封装读取文件

这里借助 Node.js 方法进行读取文件,不了解Node.js的方法可以关注我,后期会出相关专栏。

// 1.引入 fs 模块
const fs = require('fs')// 2.调用方法读取文件
// fs.readFile('./index.md',(err,data)=>{
//     // 如果失败,则抛出错误
//     if(err) throw err;
//     // 如果没有出错,则输出内容
//     console.log(data.toString());
// })// 3.使用 Promise 封装
const p = new Promise(function(resolve,reject){fs.readFile('./index.md',(err,data)=>{// 判断如果失败if(err) reject(err)// 如果成功resolve(data)})
})
p.then(function(value){console.log(value.toString());
},function(reason){console.log("读取失败!!");
})

Promise.prototype.then 方法

Promise实例具有then方法,即then方法定义在原型对象Promise.prototype上,作用是为Promise实例添加状态改变时的回调函数。案例如下:

<script>// 创建 promise 兑现const p = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('用户数据')// reject('出错啦')})})// 调用 then 方法 const result = p.then(value =>{// 如果回调函数中返回的结果是非 promise 类型属性,状态为成功,返回值为对象的成功的值console.log(value);// 1、非promise类型的属性// return 123// 2、是promise对象// return new Promise((resolve,reject)=>{//     // resolve('ok')//     // reject('error')// })// 3、抛出错误throw new Error('出错啦!!')},reason=>{console.log(reason);})// then方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定console.log(result);
</script>

then方法返回的是一个新的Promise实例,因此可以采用链式写法,即then方法后面再调用另一个then方法。但是前一个then()方法中的回调函数中又可能返回一个Promise实例,这时候后面一个then()方法中的回调函数会等前一个Promise实例状态发生变化才会调用。案例如下:

<script>let p = new Promise((resolve, reject) => {setTimeout(()=>{resolve('success')});},1000);p.then(res => {console.log(res);return `${res} again`;}).then(res => console.log(res));
</script>

Promise多文件读取

回调地狱与Promise对象实现相比,不会产生回调现象,而且也不用再数据庞大时进行大规模的缩进。承接上文单文件读取,现在进行多文件读取,案例如下:

// 1.引入 fs 模块
const { rejects } = require('assert')
const fs = require('fs')
const { resolve } = require('path')// 2.回调地狱 调用方法读取文件
// fs.readFile('./index.md',(err,data)=>{
//     fs.readFile('./index1.md',(err,data1)=>{
//         fs.readFile('./index2.md',(err,data2)=>{
//             let result = data + '\r\n' + data1 +'\r\n'+ data2
//             console.log(result);
//         })
//     })
// })// 3.使用 Promise 实现
const p = new Promise((resolve,reject)=>{fs.readFile('./index.md',(err,data)=>{resolve(data)})
})// value 是第一个文件的内容
p.then(value => {return new Promise((resolve,reject)=>{fs.readFile('./index1.md',(err,data)=>{//data是第二个文件的内容// 返回的是第一个和第二个文件合并的数组resolve([value, data])})})
}).then(value => {//这里的value就是上面合并的数组return new Promise((resolve,reject)=>{fs.readFile('./index2.md',(err,data)=>{//data是第三个文件的内容// 压入value.push(data)resolve(value)})})
}).then(value => {//如果上面成功,现在的value就是返回三个数组的合集console.log(value.join('\r\n'));//数组用join进行拼接
})

Promise.prototype.catch()

该方法用于指定发生错误时的回调函数。举个简单的例子:

<script>const p = new Promise((resolve,reject)=>{setTimeout(function(){reject('出错了!')},1000)})// p.then(value=>{},reason=>{//     console.log(reason);// })p.catch(reason=>{console.log(reason);})
</script>

Promise.prototype.finally()

finally()方法指定不管promise最后的状态如何,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数。

<script>const p = new Promise((resolve,reject)=>{setTimeout(function(){reject('出错了!')},1000)})p.catch(reason=>{console.log(reason);}).finally(()=>{console.log('我是finall,不管promise结果如何我都要执行');})
</script>

Promise.all()

该方法用于将多个 Promise 实例包装成一个新的 Promise 实例,方法接受一个数组作为参数,数组参数都是Promsie实例。当然参数也可以不是数组,但必须有Iterator接口,且返回的每个成员都是Promise实例。

该方法只适合所有异步都操作成功的情况,如果有一个操作失败就无法满足要求。

<script>// Promise.all()的状态由参数决定:分以下两种情况/* * (1)Promise.all()参数的状态都变成fulfilled,Promise.all()状态才会变成fulfilled,此时所有参数的返回值组成一个数组,传递给Promise.all()的回调函数。* (2)只要参数之中有一个被rejected,Promise.all()的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。*/const p1 = new Promise((resolve, reject) => {resolve('hello');}).then(result => result);const p2 = new Promise((resolve, reject) => {throw new Error('报错了');}).then(result => result);Promise.all([p1, p2]).then(result => console.log(result)).catch(e => console.log(e));//Error:报错了
</script>

Promise.race()

该方法同样是将多个 Promise 实例包装成一个新的 Promsie 实例,该方法与 Promise.all()方法一样,区别是该方法中只要参数之中有一个实例率先改变状态,该方法的实例状态跟着改变,那个率先改变的 Promise 实例的返回值就传递给该方法实例的回调函数。

<script>const p = Promise.race([fetch('./index.js'),new Promise(function (resolve, reject) {setTimeout(() => reject(new Error('request timeout')), 5000)})]);p.then(console.log).catch(console.error);
</script>

上面代码中,如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变成rejected,从而触发catch方法指定的回调函数。

Promise.allSettled()

该方法用来确定一组异步是否都结束(不管成功或失败)。方法接受一个数组作为参数,只有当参数数组中所有 Promise对象 都发生变化,返回的 Promise 对象才会发生状态变更。

<script>const resolved = Promise.resolve(42);const rejected = Promise.reject(-1);const allSettledPromise = Promise.allSettled([resolved, rejected]);allSettledPromise.then(function (results) {console.log(results);});
</script>

回调函数接受到的参数是数组results,该数组的每一个成员都是一个对象,对应传入Promise.allSettled()的数组里面的两个 Promsie 对象。

Pomise.any()

Promise.any()和Promise.race()方法很像,唯一区别就是Promise.any()不会因为某个 Promise 变成 rejected 状态而结束,必须等到所有参数 Promise 变成 rejected 状态才会结束。

var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);Promise.any([resolved, rejected, alsoRejected]).then(function (result) {console.log(result); // 42
});Promise.any([rejected, alsoRejected]).catch(function (results) {console.log(results instanceof AggregateError); // trueconsole.log(results.errors); // [-1, Infinity]
});

Promise.resolve()

该方法能够将现有对象转换为 Promise 对象。

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

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

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

相关文章

微信小程序开发入门与实战(Behaviors使用)

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; 微信小程序 &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f4…

【原创】基于JavaWeb的社区疫情防控管理系统(疫情防控管理系统毕业设计)

项目介绍&#xff1a;后端采用JspServlet。前端使用的是Bootstrap的一个网站模板。开发一个在线的社区疫情防控管理系统。从角色的划分&#xff0c;包括用户、社管员、管理员。功能模块上包括了社区公告发布、高风险地区记录、地区感染信息管理、社区出入登记管理、行程信息管理…

关于maven生命周期的理解

晚上有点无聊&#xff0c;看到了一些东西引发了自己的思路&#xff0c;就想将maven的一些东西总结总结&#xff0c;有从网上抄的&#xff0c;也有自己的思路。 一、生命周期是指什么&#xff08;lifecycle&#xff09; Maven的生命周期就是对所有的构建过程进行抽象和统一。包…

Posix与System V IPC

Posix与System V IPC一、Posix IPC1.概述2.IPC名字3.px_ipc_name函数3.创建与打开IPC通道4.IPC权限二、System V IPC1.概述2.key_t键和ftok函数3.ipc_perm结构4.创建与打开IPC通道5.IPC权限6.标识符重用7.ipcs和ipcrm程序8.内核限制一、Posix IPC 1.概述 三种类型的IPC合称为…

Redux的基本使用过程详解

文章目录Redux的使用过程Redux测试项目的搭建Redux的基本使用步骤Redux目录的结构划分React的三大原则Redux的使用过程 Redux测试项目的搭建 1.创建一个新的项目文件夹:learn-redux # 执行初始化操作 npm init -y或yarn init -y # 安装redux:npm install redux --save或yarn …

自定义View 布局过程(Layout)

目录一、作用二、layout过程详解2.1单一View的layout过程具体使用具体流程源码分析总结2.2ViewGroup的layout过程具体使用具体流程源码分析总结三、细节问题&#xff1a;getWidth() &#xff08; getHeight()&#xff09;与 getMeasuredWidth() &#xff08;getMeasuredHeight(…

Java高级——编译JDK

编译JDKJDK是什么&#xff1f;编译环境搭建JDK下载编译参数编译在IDE中调试源码JDK是什么&#xff1f; Java Development Kit&#xff0c;用于执行和开发java程序 编译环境搭建 本文采用Ubantu 18.04 执行以下命令安装依赖 apt-get install build-essential apt-get instal…

Transformer

参考 https://www.ylkz.life/deeplearning/p12158901/ https://zhuanlan.zhihu.com/p/396221959 模型结构 Input Embedding 将文本中词汇的数字表示转变为向量表示, 希望得到其在高维空间中的特征表示向量。 # 导入必备的工具包 import torch import torch.nn as nn import …

Qt5开发从入门到精通——第九篇一节( Qt5 文件及磁盘处理—— 读写文本文件)

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 欢迎小伙伴的点评✨✨&#xff0c;相互学习c/c应用开发。&#x1f373;&#x1f373;&#x1f373; 博主&#x1f9d1;&#x1f9d1; 本着开源的精神交流Qt开发的经验、将持续更新续章&#xff0c;为社区贡献博主自身的开源精…

esp32-C3 CAN接口使用

esp32-C3 CAN接口使用功能概述CAN协议关注点接收过滤器单过滤器模式双过滤器模式关键函数说明配置和安装驱动获取TWAI状态信息发送/接收消息使用示例CAN控制器自回环测试CAN收发带过滤测试功能概述 ESP32-C3具有1个CAN控制器支持以下特性&#xff1a; 兼容ISO 11898-1协议(CA…

伟大的micropython smartconfig 配网它来了!!!

我这其实只是实验和搬运&#xff0c;还是感谢伟大的walkline群主&#xff0c;他弄好的&#xff0c;我只是负责搬运发布给新手看。 之前一大堆人问我配网的事儿&#xff0c;输入下wifi名称密码这么麻烦吗&#xff0c;好吧&#xff0c;有求必应&#xff0c;之前的配网是通过ap模式…

PICO高管专访:关于PICO 4硬件、内容、定价、海外布局的一切解答

PICO 4昨天正式在国内发布&#xff0c;简单来说这是一款相对均衡的VR一体机&#xff0c;在硬件素质、内容生态建设上都可圈可点&#xff0c;对于国内还未入手VR的朋友们来说是非常好的选择。相关阅读&#xff1a;《PICO 4评测&#xff1a;Pancake光学新标杆&#xff0c;VR娱乐V…

20【访问者设计模式】

文章目录二十、访问者设计模式20.1 访问者设计模式简介20.1.1 访问者设计模式概述20.1.2 访问者设计模式的UML类图20.2 访问者设计模式的实现20.3 访问者设计模式的优缺点二十、访问者设计模式 20.1 访问者设计模式简介 20.1.1 访问者设计模式概述 访问者设计模式&#xff0…

计算机网络基础 VLSM----可变长子网掩码;CIDR技术----无类域间路由;

VLSM----可变长子网掩码&#xff1a; 概述&#xff1a; 通过网络位向主机位借位的方式&#xff0c;延长子网掩码&#xff0c;从而达到将一个大网络划分为多个小网络&#xff1b;借出的位数称之为子网位&#xff0c;决定了能划分网络的个数。 优点&#xff1a; 更高效的利用…

记一次导入下载好的源码工程到本地工程异常解决方案

今天在学习okhttp相关视频时&#xff0c;安装视频的操作在自己的工程中引入三方的模块&#xff0c;但是发现引入后和预期的不一致。不一致指的是&#xff0c;视频中以module方式引入sample-okhttp并解决冲突后&#xff0c;sample-okhttp能够被android stuidio识别为applicayion…

Style样式设置器

构成Style最重要的两种元素&#xff1a; Setter类帮助我们设置控件的静态外观风格 Trigger类则帮助我们设置控件的行为风格。 Setter,设置器&#xff0c;我们给属性赋值的时候一般都采用“属 性名属性值”的形式 上面的例子中针对TextBlock的Style&#xff0c;Style中使用 若…

解决csdn强制关注博主才能阅读文章

问题 有的时候查阅资料的时候,关注博主并不是很方便,查csdn会出现下面的提示解决办法 打开控制台输入以下代码: var article_content=document.getElementById("article_content"); article_content.removeAttribute("style");var follow_text=document…

深入理解计算机系统——第七章 Linking

深入理解计算机系统——第七章 Linking7.1 Compiler Drivers7.2 Static Linking7.3 Object Files7.4 Relocatable Object Files7.5 Symbols and Symbol Tables7.6 Symbol Resolution7.6.1 How Linkers Resolve Duplicate Symbol Names7.6.2 Linking with Static Libraries7.6.3…

人体神经元结构示意图,神经细胞内部结构图

人体神经结构图&#xff1f;&#xff1f;&#xff1f;&#xff1f; 谷歌人工智能写作项目&#xff1a;神经网络伪原创 下图为神经系统的结构示意图&#xff0c;请根据图回答&#xff1a; &#xff08;1&#xff09;构成神经系统的结构、功能单位是神经元&#xff0c;图中E部分…

19【迭代器设计模式】

文章目录十九、迭代器设计模式19.1 迭代器设计模式简介19.1.1 迭代器设计模式概述19.1.2 迭代器设计模式的UML类图19.2 迭代器设计模式的实现19.3 迭代器设计模式的优缺点十九、迭代器设计模式 19.1 迭代器设计模式简介 19.1.1 迭代器设计模式概述 迭代器设计模式&#xff0…