Promise处理异步的并行和串行

news2024/11/25 8:19:10

一、异步的“并行”

同时处理,相互之间没啥依赖

// 执行FN1返回一个promise实例,实例中管理了一个异步编程的代码,当定时器到时间后,才会把实例的状态改为成功
const fn1 = () => {return new Promise(resolve => {setTimeout(() => {resolve(1);}, 1000);});
};
const fn2 = () => {return new Promise(resolve => {setTimeout(() => {resolve(2);}, 2000);});
};
const fn3 = () => {return new Promise(resolve => {setTimeout(() => {resolve(3);}, 3000);});
}; 

// 异步的“并行”:同时处理,相互之间没啥依赖
fn1().then(result => {console.log(result);
});
fn2().then(result => {console.log(result);
});
fn3().then(result => {console.log(result);
}); 

并行中的综合处理

一起发送多个请求(处理多个异步),但是需要等到所有异步都成功,我们再整体做啥事!!

  • 语法:let promise = Promise.all([promise1,promise2,…]);* 执行Promise.all返回一个新的promise实例 @P* 并且传递一个数组,数组中包含N多其它的promise实例* 如果数组中的每一个promise实例最后都是成功的,则@P也将会是成功的,它的值也是一个数组,按照顺序依次存储各个promise实例的结果;但凡数组中的某个promsie实例是失败的,则@P也是失败的,值是当前这个实例失败的原因!* 如果数组中有一项并不是promise实例(例如:是个100),则浏览器也会把其默认变为一个状态是成功的promsie实例,值就是当前项本身```
    let p = Promise.all([Promise.resolve(100), fn1(), 200, fn3(), fn2()]); //浏览器默认会把200 变为一个成功的promsie实例
    p.then(results => {console.log(成功:${results}); // 成功:100,1,200,3,2 顺序和最开始是一致的,不会考虑谁先成功
    }).catch(reason => {console.log(失败:${reason});
    });

//new Error(‘xxx’)不是promise实例=》Promise.resolve(new Error(‘xxx’)) 值是Error对象
let p = Promise.all([Promise.resolve(100), fn1(), new Error(‘xxx’), Promise.reject(200), fn3(), fn2()]);
p.then(results => {console.log(成功:${results});
}).catch(reason => {console.log(失败:${reason}); //失败:200 遇到错误直接返回
});

//=>等三个异步都成功做什么事情 所用时间3s
Promise.all([fn1(), fn2(), fn3()]).then(results => {console.log(三个异步都成功了,分别的结果:${results});
});


二、异步的“串行”:
==========

第一个异步成功才能发送第二个,第二个成功才能发送第三个....多个异步之间一般是有依赖的

2.1 then链机制处理
-------------

promise状态是失败,如果不用catch(或者onrejected)处理,控制台会抛出异常:Uncaught (in promise) xxx,但是此异常不会阻碍下面代码执行!!

fn1().then(result => {console.log(第一个成功:${result});return fn2();
}).then(result => {console.log(第二个成功:${result});return fn3();
}).then(result => {console.log(第三个成功:${result});
}).catch(reason => {console.log(只要其中一个失败,直接顺延到这里,其余剩下的请求就不发送了!);
});


2.2 真实项目中,想实现异步的串行,我们一般使用async+await
------------------------------------

(async function () {let result = await fn1();console.log(第一个成功:${result});result = await fn2();console.log(第二个成功:${result});result = await fn3();console.log(第三个成功:${result});
})();


2.3 promise.then(onfulfilled,onrejected) 在内存中的执行
------------------------------------------------

首先,我们复习一下事件循环机制 EventLoop

* 同步代码执行,遇到一个异步任务* 1. 先把其放在 WebAPI 进行监听* 2. 当前异步任务监听到可以执行了,则再把其放在EventQueue中,排队等待执行* 同步任务执行完,主线程空闲下来*  1. 去EventQueue中找可执行的微任务,如果微任务中都执行完了,再去找可执行的宏任务「队列:优先级队列 & 先进先出」* 2. 取到的任务都放在Stack中交给主线程去执行*  ......那么接下来我们来了解一下promise.then(onfulfilled,onrejected) 在内存中的执行

**promise.then(onfulfilled,onrejected) 在内存中的执行**

* 情况一:我此时已经知道promise是成功还是失败的*  我们此时应该去执行onfulfilled或者onrejected,但是不是立即执行,它是一个异步的微任务* 首先把执行对应的方法这个事情放在WebAPI中监听,但是因为此时已经知道状态了,对应的方法肯定可以执行,所以紧接着把它挪至到EventQueue中「异步微任务队列」等待执行* 情况二:此时的promise还是pending状态*  我们把onfulfilled/onrejected先存储起来,只有当后面,我们把实例的状态修改为成功/失败的时候,再取出之前存储的方法,把其执行「而且此时再执行,还是个异步微任务」* 还是要经历:WebAPI -> EventQueue三、aysnc修饰符
==========

**aysnc最主要的作用就是:如果想在函数中使用await,则当前函数必须基于async修饰**

aysnc修饰符,让函数的返回值成为一个promise实例 这样就可以基于THEN链去处理了

* 如果函数自己本身就返回一个promise实例,则以自己返回的为主* 如果函数自己本身没有返回promise,则会把返回值变为一个promise实例:状态=> 成功 值=>返回值* 如果函数执行报错则返回的实例状态是失败,值是报错原因,但不影响下面代码执行```
async function fn() {return 10;
}
fn().then(result => {console.log(result);//输出10
}); 

async function fn() {return async function () {return 10;};
}
fn().then(result => {// result:async function () {...}函数return result();
}).then(result => {console.log(result); //10
}); 

四、await:等待

  • 我们一般在其后面放promise实例 它会等待实例状态为成功,再去执行“当前上下文”中 ,await下面的代码

【如果promise实例管控的是一个异步编程,其实它是在等待异步成功,再执行下面的代码,类似于把异步改为同步的效果】

  • await 10 =>默认转为 await Promise.resolve(10)* 如果后面放的不是promise实例,则浏览器默认把其转换为”状态为成功,值就是这个值 " 的实例
const fn1 = () => {return new Promise(resolve => {setTimeout(() => {resolve(1);}, 1000);});
};
(async function () {let result = await fn1();console.log(result); //下面代码可以执行,说明await后面的promise实例,它的状态已经是成功了,await的返回值就是当前promise实例的值console.log('OK');
})(); 

//=======================如果await后面的promise实例状态是失败的
const fn1 = () => {return new Promise((resolve, reject) => {setTimeout(() => {reject(0);}, 1000);});
};
(async function () {let result = await fn1(); //如果await后面的promise实例状态是失败的,则下面代码永远都不会执行了console.log(result);console.log('OK');//如果是失败的则这句话不会执行
})();

//===================================================
(async function () {let a = await 10; //->Promise.resolve(10)console.log(a); //10let b = await Promise.resolve(20);console.log(b); //20try {let c = await Promise.reject(30); //Uncaught (in promise) 30console.log(c);} catch (err) {console.log(err); //30}console.log('OK'); //'OK'
})(); 

await中的异步

await中的异步:当前上下文,await下面的代码执行是异步微任务

  • 情况1:await后面的promise实例我们已知是成功的先把微任务放置在WebAPI中,但是知道是可以执行的,则直接在挪至到EventQueue中等待执行* 情况2:await后面的promise实例还是pending状态 此时我们把微任务放置在WebAPI中监听,等到后期promise实例是成功态后,再把它挪至到EventQueue中等待执行即可
(async function () {let b = await Promise.resolve(20);console.log(b);
})() 

五、思考题

思考题1

console.log(1);
setTimeout(() => { console.log(2); });//宏1
console.log(3);
let p1 = new Promise(resolve => {//new Promise 立即会把executor函数执行 是同步console.log(4);resolve('A'); //执行resolve P1的状态是成功=》已知console.log(5);
});
console.log(6);
p1.then(result => {//.then是异步 已知状态 放进WebAPI中监听 但是因为是已知状态 方法肯定执行 则从WebAPI监听队列挪到EventQueue中等待console.log(result); //微1
});
console.log(7);
let p2 = new Promise(resolve => { //立即执行executor函数 setTimeout是异步则会放进WebAPI监听 宏2setTimeout(() => {resolve('B');console.log(10); //执行宏2=>@1 更改了p2的状态 @2之前存储的.then方法执行});
});
console.log(8);
p2.then(result => {//p2的状态是未知则会先存起来console.log(result);
});
console.log(9); 

思路及图解

思考题2

基于事件绑定属于异步宏任务

let body = document.body;
body.addEventListener('click', function () {Promise.resolve().then(() => {console.log(1);});console.log(2);
});
body.addEventListener('click', function () {Promise.resolve().then(() => {console.log(3);});console.log(4);
}); 

思路及图解

思考题3

 async function async1() {console.log('async1 start');await async2();console.log('async1 end');
}
async function async2() {console.log('async2');
}
console.log('script start');
setTimeout(function () {console.log('setTimeout');
}, 0)
async1();
new Promise(function (resolve) {console.log('promise1');resolve();
}).then(function () {console.log('promise2');
});
console.log('script end'); 

思路及图解

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

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

相关文章

nginx使用!

一:概述 Nginx (“engine x”) 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用 Nginx 网站用户有:百度、京…

NTN(二) Timing Advance

微信同步更新欢迎关注同名modem协议笔记 地面移动系统的传播延迟通常小于 1 毫秒。 相比之下,NTN 中的传播延迟要长得多,延迟从几毫秒到数百毫秒不等,具体取决于星载或机载平台的高度以及 NTN 中的payload类型。 因此对NTN系统,处…

Java 脚本引擎的使用

1. 前言 Java 6 版本就已经引入了 Rhino 引擎用以支持脚本代码运行,而从 Java 8 开始 Nashorn 取代 Rhino 成为 Java 内嵌的 JavaScript 引擎。Nashorn 引擎允许开发人员将 JavaScript 代码嵌入到 Java 中执行,这个特性在复杂的配置系统中有比较大的应用…

javascript reduce()方法

相信挺多人对这个方法还是那么的陌生,其实也能理解,毕竟它能做到的事情还有其他的方法能做到。下面就说一下我个人的理解吧!!!reduce()方法:用法:array.reduce(function(total,currentData,curr…

管理bug的工具

一、国内的bug管理软件: 1、禅道 禅道是第一款国产开源项目管理软件。它的核心管理思想基于敏捷方法scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能。在一个软件中就…

nodejs+vue+element+eachers构建开源项目大型连续剧(5)前端请求封装,完成用户注册。

在前端项目开发中,一个好的请求封装可以给我们带来诸多便利,减少了代码重复,优化了问题处理等。那接下来我们一起学习一下怎么做到对一个请求的简单封装吧。主要通过对axios请求的二次封装,实现页面的请求以及必要的优化。 一、引…

Word处理控件Aspose.Words功能演示:在 C# 中将 Word DOC DOCX 转换为 Markdown

Aspose.Words 是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。此外, Aspose API支持流行文件格式处…

每个Java程序员都必须知道的四种负载均衡算法

前言 一般来说,我们在设计系统的时候,为了系统的高扩展性,会尽可能的创建无状态的系统,这样我们就可以采用集群的方式部署,最终很方便的根据需要动态增减服务器数量。但是,要使系统具有更好的可扩展性&…

【UE4 第一人称射击游戏】32-添加击杀AI的提示功能(使用到控件蓝图的动画功能)

上一篇:【UE4 第一人称射击游戏】31-更好的UI界面本篇效果:可以看到在击杀AI后,右上角有击杀提示信息步骤:新建一个控件蓝图命名为“KillPopup”双击打开“KillPopup”,拖入一个图像控件,锚点设置为右上角&…

RobotFramework测试库

在RF 测试库里面,分为三种测试库标准测试库扩展测试库远程测试库标准测试库随 Robot Framework 版本一同发布的测试库, 不需要单独安装,但部分标准库仍然需要手动导入标准库有扩展测试库标准库以外的其他测试库都统称为扩展测试库&#xff0c…

OceanBase产品家族及基础概念

第二章:OceanBase产品家族及基础概念 1. OceanBase产品家族 1.1 OceanBase数据库产品家族 1.2 OceanBase数据库内核 1.2.1 高扩展 • 水平扩展 • 按需在线扩容、缩容、不停服务 • 单集群突破100台服务器 1.2.2 高性能 • 峰值6,100万次/秒(真实业…

P12 PyTorch 常见函数梯度

目录:1: 常见函数的导数2: 梯度与微分的关系3: 常见函数的梯度4: 梯度更新常见问题一 常见函数的导数(复合函数求导证明)二 梯度与微分的关系2.1 微分: x 为一元变量时微分: x 为向量时微分矩阵…

学术加油站|机器学习应用在数据库调优领域的前沿工作解读

编者按 本文系北京理工大学科研助理牛颂登所著,本篇也是「 OceanBase 学术加油站」系列稿件第八篇。 「牛颂登:北京理工大学科研助理。 硕士期间在电子科技大学网络空间安全研究院从事聚类和强化学习相关算法研究,在应用聚类研究个性化在线学…

Python之Hermite多项式

文章目录Hermite多项式求导和积分求根和反演拟合其他Hermite多项式 Hermite多项式是一种非常重要的正交多项式,尤其在量子力学中,是谐振子的本征态,在物理学中,其定义为 Hn(x)(−1)nex2dndxne−x2H_n(x)(-1)^ne^{x^2}\frac{\text…

算法之动态规划实战

目录 前言: 如何量化两个字符串的相似度? 如何编程计算莱文斯坦距离? 如何编程计算最长公共子串长度? 参考资料 前言: 利用 Trie 树,可以实现搜索引擎的关键词提示功能,这样可以节省用户输…

【Python+pandas】学生测试成绩求和排序

✨博文作者 wangzirui32 💖 喜欢的可以 点赞 收藏 关注哦~~ 👉本文首发于CSDN,未经许可禁止转载 😎Hello,大家好,我是wangzirui32,最近时间不够充足,鸽了几个月,这是2023…

【蓝桥杯第十三届C++B组】真题训练(5 / 8) - java写法

目录 4402.刷题统计 - 数学模拟 4403. 修剪灌木 - 思维 4404. X 进制减法 - 进制运算 贪心 4405. 统计子矩阵 - 前缀和 双指针​​​​​​​ 1、一维前缀和 2、二维前缀和 4406. 积木画 - dp 1、找规律dp 4402.刷题统计 - 数学模拟 4402. 刷题统计 - AcWing题库 思…

素数(prime)总结

素数的介绍 素数定义 质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。 根据算术基本定理,每一个…

linux 文件夹多用户共享 解决文件删除的Permission denied

linux文件属性基础 Linux文件属主和属组 通过命令ls 可以查看文件属性: zcargo-MS-7D53:~/Desktop/parent_ceshi$ ll -lh total 16K drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi/ drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi02/以上展示命令的意思&#xff1…

大数据概念及Hadoop介绍

大数据概念及Hadoop介绍大数据概念数据存储单位大数据定义大数据的特点(5V特征)大数据部门组织架构分布式技术负载均衡故障转移伸缩性分布式技术总结分布式和集群的区别Hadoop介绍Hadoop核心组件Hadoop发展简史Hadoop特性优点与行业应用Hadoop特性优点行业应用Hadoop发行版本及…