ES6新标准下JS异步编程Promise解读

ES5及以下,要实现复杂的异步编程,需要大量运用回调函数,每一个回调函数(JS引擎把它当作一个代码块)依次进入单线程(JS)任务队伍依次执行,而每个回调函数中的执行正确与否无法及时判断,当中信息反馈及显示都只会在最外层函数执行完毕后才反馈给你,让你只能猜测或分析找问题,这将造成大量无法理解的情况出现。对于复杂嵌套回调问题,你将不得不花费大量精力去跟踪各个回调函数运行及清理相互影响。

ES6新标准引入Promise对上述问题进行解决,它的核心思想,是将上一次函数执行返回一个Promise对象,明确指示代码是否成功执行,则你可以基于此成功与否判断,以链式编程方式将复杂嵌套回调函数转换为简单流程化式的形式完成目标任务。

一、Promise的基本用法

每个Promise都会经历一个短暂的生命周期,当处于进行中时标记为pending状态,一旦异步操作结束,Promise标记为settled状态,如果操作出现错误或未完成,标记为unsettle状态。其内部属性[[PromiseState]],分别对应这三种状态,分别是”pending”、“fulfilled”和”rejected”。其内部会自动调用then()方法响应fulfilled成功状态,catch()方法响应rejected。

Then()方法调用时,与异步操作相关的附加数据都会传递给这个完成响应函数。Catch()调用时,所有与失败状态相关的附加数据都会传递给这个拒绝响应函数。

1.基本用法

Promise构造函数可以创建Promise,构造函数接受两个参数,分别是resolve()函数与reject()函数,执行成功完成时调用resolve()函数,失败时则调用reject()函数。

Promise.resolve方法是将一个对象转换成Promise对象,如果入参是一个Promise对象,则直接返回该对象;如果入参是一个thenale对象(表示该对象已经调用了then方法),则返回的是一个新的Promise对象;如果无任何参数,则返回一个fulfilled状态的Promise对象。

Promise.reject方法可以快速返回被rejected的Promise对象。该方法接收一个参数作为入参,这个参数将成来被rejected对象的reason属性,传给rejected回调函数。

       let promise1=new Promise(function(resolve,reject){//模拟函数成功执行

              resolve("成功");

       });

       promise1.then(function(contents){

              console.log(contents);//输出---成功

       });

       let promise2=new Promise(function(resolve,reject){//模拟函数拒绝执行

              reject(new Error("拒绝"));

       });

       promise2.catch(function(err){

              console.log(err);//输出---Error:拒绝

       });

2.具体运用实例

function readNumber(num){//定义Promise实例函数

       return new Promise(function(resolve,reject){

                     if(num<0){

                            reject("输入的数字小于0,拒绝兑换");

                            return;

                     }

                     resolve("输入的数字大于0,执行兑换");

       });

}

let promise1=readNumber(45);//执行成功输入

promise1.then(function(contents){

       console.log(contents);//输出结果:输入的数字大于0,执行兑换

});

promise1.catch(function(err){

       console.log(err);//此函数不会被调用,故无此输出

});

let promise2=readNumber(-6);//执行失败输入

promise2.then(function(contents){

       console.log(contents);//此函数不会被调用,故无此输出

});

promise2.catch(function(err){

       console.log(err);//输入的数字小于0,拒绝兑换

});

二、Promise的串联(链式)用法

Promise每次调用then()方法和catch()方法时,实际上创建了另一个Promise,只有当第一个Promise完成或被拒绝时,第二个才会被解决。因此,就给解决复杂问题链式化提供了条件,而不是用复杂或嵌套式回调函数去解决。其写法如下:

Let p1=new Promise(function(resolve,reject){ });

P1.then(function(){ }).then(funciton(){ })…

以上述实例为具体实现,如下:

function readNumber(num){//定义Promise实例函数

       return new Promise(function(resolve,reject){

                     if(num<0){

                            reject("输入的数字小于0,拒绝兑换");

                            return;

                     }

                     resolve("输入的数字大于0,执行兑换");

       });

}

let promise1=readNumber(45);//执行成功输入

promise1.then(function(contents){

       console.log(contents);//输出结果:输入的数字大于0,执行兑换

}).then(function(){

       console.log("由于有兑换劵,就可以进入购买了");//输出结果:由于有兑换劵,就可以进入购买了

});

let promise2=readNumber(-8);//执行失败输入

promise2.then(function(contents){

       console.log(contents);//输出结果:输入的数字大于0,执行兑换

}).then(function(){

       console.log("由于有兑换劵,就可以进入购买了");//无输出结果:由于readeNumber输入的是-8,第一个then不满足,为拒绝状态,因而第二个then没有调用,而第三个then是基于第二个then呈错误状态的,所有第三个then被执行

}).catch(function(){

       console.log("由于没有有兑换劵,无法进入");//输出结果:由于没有有兑换劵,无法进入

})

三、多Promise响应用法

    如果你想通过多个Promise来决定下一步的操作,则可以使用ES6提供的Promise.all()和Promise.race()两个方法来监听多个Promise。

    1.Promise.all()方法

Promise.all()方法只接受一个参数并返回一个Promise,该参数是一个含有多个受监视Promise的可迭代对象(例如,一个数组),只有当可迭代对象中所的Promise都被解决后返回的Promise才会被解决,只有当可迭代对象中所有Promise都被完成返回后的Promise才会被完成。

let p1=new Promise(function(resolve,reject){

       resolve(42);

});

let p2=new Promise(function(resolve,reject){

       resolve(43);

});

let p3=new Promise(function(resolve,reject){

       resolve(44);

});

let p4=Promise.all([p1,p2,p3]);

p4.then(function(value){ //因为P4呈完成状态,所以没有调用catch,而是调用的then方法

       console.log(Array.isArray(value));//输出结果:true

       console.log(value[0]);//输出结果:42

       console.log(value[1]);//输出结果:43

       console.log(value[2]);//输出结果:44

})

    上述例中,只有当迭代中所有都完成,P4才呈完成状态;反之,只要有一个被拒绝,那么返回的Promise没等其他后面Promise完成就立即呈拒绝状态。如下:

    let p1=new Promise(function(resolve,reject){

              resolve(42);

       });

       let p2=new Promise(function(resolve,reject){

              reject(43);

       });

       let p3=new Promise(function(resolve,reject){

              resolve(44);

       });

       let p4=Promise.all([p1,p2,p3]);

       p4.catch(function(value){//因为P4呈拒绝状态,所以没有调用then,而是调用的catch方法

              console.log(Array.isArray(value));//输出结果:false

              console.log(value);//输出结果:43

       });

2.Promise.race()方法

Promise.race()方法也监听多个Promise,与Promise.all方法不一样,它只要有一相Promise被解决则立即返回呈解决状态,无须等到所有的Promise都被解决。

let p1=new Promise(function(resolve,reject){

       resolve(42);

});

let p2=new Promise(function(resolve,reject){

       resolve(43);

});

let p3=new Promise(function(resolve,reject){

       resolve(44);

});

let p4=Promise.race([p1,p2,p3]);

p4.then(function(value){//只要p1呈完成状态,就立即返回呈完成状态,其他后面Promise则被忽略

       console.log(Array.isArray(value));//输出结果:false

       console.log(value);//输出结果:42

});

实际上,传给Promise.race()方法的Promise会进行竞选,以决出哪一个先被解决完成,就选哪一个,并以最先解决状态而呈相同状态,其他的则被忽略。

let p1=new Promise(function(resolve,reject){

       setTimeout(function(){resolve(42);},200);

});

let p2=new Promise(function(resolve,reject){

       resolve(43);

});

let p3=new Promise(function(resolve,reject){

       resolve(44);

});

let p4=Promise.race([p1,p2,p3]);

p4.then(function(value){//由于p1被延迟执行,所以p2最先呈完成状态,故最后输出为p2状态

       console.log(Array.isArray(value));//输出结果:false

       console.log(value);//输出结果:43

});

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

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

相关文章

【ShuQiHere】 探索数据挖掘的世界:从概念到应用

&#x1f310; 【ShuQiHere】 数据挖掘&#xff08;Data Mining, DM&#xff09; 是一种从大型数据集中提取有用信息的技术&#xff0c;无论是在商业分析、金融预测&#xff0c;还是医学研究中&#xff0c;数据挖掘都扮演着至关重要的角色。本文将带您深入了解数据挖掘的核心概…

如何快速上手一个Github的开源项目

程序研发领域正是有一些热衷开源的小伙伴&#xff0c;技能迭代才能如此的迅速&#xff0c;因此&#xff0c;快速上手一个GitHub上的开源项目&#xff0c;基本上已经变成很个程序员小伙伴必须掌握的技能&#xff0c;因为终究你会应用到其中的一个或多个项目&#xff0c;帮助自己…

【计算机网络篇】电路交换,报文交换,分组交换

本文主要介绍计算机网络中的电路交换&#xff0c;报文交换&#xff0c;分组交换&#xff0c;文中的内容是我认为的重点内容&#xff0c;并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 目录 &#x1f3af;一.划分…

【Windows 同时安装 MySQL5 和 MySQL8 - 详细图文教程】

卸载 MySQL 参考文章&#xff1a; 完美解决Mysql彻底删除并重装_怎么找到mysql并卸载-CSDN博客使用命令卸载mysql_卸载mysql服务命令-CSDN博客 先管理员方式打开 cmd &#xff0c;切换到 MySQL 安装目录的 bin 文件夹下&#xff0c;执行如下命令&#xff0c;删除 MySQL 服务mys…

Blender软件三大渲染器Eevee、Cycles、Workbench对比解析

Blender 是一款强大的开源3D制作平台&#xff0c;提供了从建模、雕刻、动画到渲染、后期制作的一整套工具&#xff0c;广泛应用于电影、游戏、建筑、艺术等领域。 渲染101云渲染云渲6666 相比于其他平台&#xff0c;如 Autodesk Maya、3ds Max 或 Cinema 4D&#xff0c;Blende…

neo4j关系的创建删除 图的删除

关系的创建和删除 关系创建 CREATE (:Person {name:"jack"})-[:LOVE]->(:Person {name:"Rose"})已有这个关系时&#xff0c;merge不起效果 MERGE (:Person {name:"Jack" })-[:LOVE]->(:Person {name:"Rose"})关系兼顾节点和关…

C++ 进阶之路:非类型模板参数、模板特化与分离编译详解

目录 非类型模版参数 类型模板参数 非类型模板参数 非类型模板参数的使用 模板的特化 函数模板的特化 类模板的特化 全特化与偏特化 偏特化的其它情况 模板的分离编译 什么是分离编译 为什么要分离编译 为什么模板不能分离编译 普通的类和函数都是可以分离编译的…

git show 命令

查看指定stash git stash show "ac-dev" # 显示存储条目中记录的更改&#xff0c;作为首次创建存储条目时存储内容和提交回之间的差异。 git stath show -p "ac-dev" # 可以查看特定 stash 的全部diff 查看tag信息 git show [tag] gi…

LeetCode 面试经典150题 67.二进制求和

415.字符串相加 思路一模一样 题目&#xff1a;给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 eg&#xff1a; 输入a“1010” b“1011” 输出“10101” 思路&#xff1a;从右开始遍历两个字符串&#xff0c;因为右边是低位先运算。如果…

【学习笔记】数据结构(六 ①)

树和二叉树 &#xff08;一&#xff09; 文章目录 树和二叉树 &#xff08;一&#xff09;6.1 树(Tree)的定义和基本术语6.2 二叉树6.2.1 二叉树的定义1、斜树2、满二叉树3、完全二叉树4、二叉排序树5、平衡二叉树&#xff08;AVL树&#xff09;6、红黑树 6.2.2 二叉树的性质6.…

opengauss使用遇到的问题,随时更新

一、查看数据库状态的方式 1、gs_ctl -D /opt/huawei/install/data/dn/ status 2、gs_om -t status --detail 3、cm_ctl query -Cv二、opengauss打印WDR性能报告 1、开启WDR性能参数开关 gs_guc reload -N all -D /opt/huawei/install/data/dn -c "enable_wdr_snap…

通用大模型 vs 垂直大模型:谁将赢得AI战场?

引言 在人工智能领域&#xff0c;大模型的快速发展引发了广泛的关注和讨论。大模型&#xff0c;尤其是基于深度学习和海量数据训练的模型&#xff0c;已经在多个领域展现出强大的能力。从自然语言处理、图像识别到自动驾驶和医疗诊断&#xff0c;AI大模型正深刻改变着我们的生…

基于二自由度汽车模型的汽车质心侧偏角估计

一、质心侧偏角介绍 在车辆坐标系中&#xff0c;质心侧偏角通常定义为质心速度方向与车辆前进方向的夹角。如下图所示&#xff0c;u为车辆前进方向&#xff0c;v为质心速度方向&#xff0c;u和v之间的夹角便是质心侧偏角。 质心侧偏角的作用有如下三点&#xff1a; 1、稳定性…

跨境专线的网速收到什么影响

跨境专线的网速受到多种因素的影响。以下是一些主要因素&#xff1a; 1. 物理距离 地理位置&#xff1a;跨境专线通常涉及较长的物理距离。数据传输的延迟会随着距离增加而增加&#xff0c;特别是在跨越海洋或多个国家时。 2. 网络基础设施 线路质量&#xff1a;专线的物理…

SVN笔记-SVN安装

SVN笔记-SVN安装 1、在windows下安装 SVN 1、准备svn的安装文件 下载地址&#xff1a;https://sourceforge.net/projects/win32svn/ 2、下载完成后&#xff0c;在相应的盘符中会有一个Setup-Subversion-1.8.17.msi的文件&#xff0c;目前最新的版本是1.8.17&#xff0c; 这里…

使用docker创建zabbix服务器

首先保证服务器已正常安装docker&#xff0c;然后执行下面这几个容器创建命令&#xff1a; #创建MySQL容器 docker run --name mysql-server -t --restartunless-stopped -e MYSQL_DATABASE"zabbix" -e MYSQL_USER"zabbix" -e MYSQL_PASSWORD"zabbix_…

基于双向 LSTM 和 CRF 的序列标注模型

基于双向 LSTM 和 CRF 的序列标注模型 在自然语言处理中,序列标注是一项重要的任务,例如命名实体识别、词性标注等。本文将介绍如何使用 Keras 构建一个基于双向 LSTM 和 CRF 的序列标注模型。 一、引言 序列标注任务要求为输入序列中的每个元素分配一个标签。传统的方法可…

Matlab自学笔记36:日期时间型的概念、分类和创建方法

1.概念 日期时间型&#xff08;Dates and Time&#xff09;数据具有灵活的显示格式和高达毫微秒的精度&#xff0c;并且可以处理时区、夏令时和平闰年等特殊因素 2.日期时间型数据有以下三种表示方式 &#xff08;1&#xff09;Datetime型&#xff0c;表示日期时间点&#x…

opencv4.5.5 GPU版本编译

一、安装环境 1、opencv4.5.5 下载地址&#xff1a;https://github.com/opencv/opencv/archive/refs/tags/4.5.5.ziphttps://gitee.com/mirrors/opencv/tree/4.5.0 2、opencv-contrib4.5.5 下载地址&#xff1a;https://github.com/opencv/opencv_contrib/archive/refs/tags/4…

Python中的数据可视化:从基础图表到高级可视化

数据可视化是数据分析和科学计算中不可或缺的一部分。它通过图形化的方式呈现数据&#xff0c;使复杂的统计信息变得直观易懂。Python提供了多种强大的库来支持数据可视化&#xff0c;如Matplotlib、Seaborn、Plotly等。本文将从基础图表入手&#xff0c;逐步介绍如何使用这些库…