Promise学习之基本方法

2024-08-25 11:44
文章标签 学习 方法 基本 promise

本文主要是介绍Promise学习之基本方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

上一篇章我们学习了Promise的概念、基本使用、状态等等,对于Promise也有了基础的了解,那本章就对与Promise的方法作基本学习,去了解了解Promise提供了什么方法。

一、then

then处理Promise返回结果,接收两个回调函数

  • 第一个回调函数:Promise执行成功触发的回调函数,从这个函数中可以获取成功数据
  • 第二个回调函数:Promise执行失败或出错触发的回调函数

在异步代码中我们需要传入回调函数来获取返回结果,而想通过这个结果再进行异步操作,就需要继续执行同样的操作,这样就产生了回调地狱,如下展示

sum(10, 20, (result) => {console.log("执行结果1", result);sum(result, 30, () => {console.log("执行结果2", result);sum(result, 40, () => {console.log("执行结果3", result);sum(result, 50, () => {console.log("执行结果4", result);sum(result, 60, () => {console.log("执行结果5", result);console.log("执行结束");});});});});
});

这样的代码就会导致我们难以处理某个回调产生的问题、可读性差等问题,那Promise又是如何去解决的?

在调用then方法之后会返回一个Promise对象,而基于这个Promise对象可以再调用then方法,实现链式调用,也就解决回调地狱问题,光讲概念有点难以理解,上代码

function sum(a, b) {new Promise((resolve, reject) => {setTimeout(() => {resolve(a + b);}, 2000);});
}
sum(10, 20).then((result) => {// 触发成功回调console.log("执行结果1", result);return result + 30;},(err) => {// 触发错误回调console.log("出错啦!!");}).then((result) => {// 触发成功回调console.log("执行结果2", result);return result + 40;},(err) => {// 触发错误回调console.log("出错啦!!");});

then方法中,通过第一个函数可以获取到异步代码成功返回的方法,那在这个函数中我们就可以做一些其他到操作,然后继续返回结果,成为下一个then方法成功回调的数据,也就是说我们在每个then方法的两个回调单独做操作,成功回调继续求和返回结果,错误回调则处理错误。

二、catch

catch是在Promise对象中执行reject函数执行出错所触发的,为了捕获错误并返回错误结果,同样执行catch方法也会返回一个Promise对象。

catch接收一个回调函数,并接收一个参数,里面存储着错误信息异常对象

情况一:通过reject方法触发,可以获取reject所存储的数据

function fun() {return new Promise((resolve, reject) => {reject("异步代码执行出错啦!!");});
}
fun().catch((error) => {console.log(error);
});

情况二:代码执行出现错误,则可以获取到异常错误信息

function fun() {return new Promise((resolve, reject) => {throw new Error("你的代码有Bug");reject("异步代码执行出错啦!!");});
}
fun().catch((error) => {console.log(error);
});

三、finally

finally:最终的,Promise对象无论结果是成功还是失败都会触发的回调函数,不过这个函数用的比较少,可以作了解。

成功情况

function fun() {return new Promise((resolve, reject) => {resolve("success");});
}
fun().finally(() => {console.log("成功啦");
});

失败情况

function fun() {return new Promise((resolve, reject) => {reject("error");});
}
fun().finally(() => {console.log("你阻止不了我的,JOJO");
});

四、all

Promise.all()将多个Promise实例,包装一个新的Prmise实例。面试问过

const p = Promise.all([p1, p2, p3]);

p的状态由【p1, p2, p3】决定,分以下两种情况

  • 情况一:p1, p2, p3都执行成功,p的状态才会是成功的,p的成功数据由p1, p2, p3的成功数据组合而成
  • 情况二:p1, p2, p3其他一个执行失败,那么p的状态就会是失败的,p失败回调的数据由最先失败的Promise实例决定

业务场景

  • 需要等待三个异步执行完成才会继续往下执行,当然可以通过async、await去实现,但是这样会导致其他异步等待这一个异步代码执行完成才会执行,这样就会耗费较多的时间,导致用户体验不好,这就可以使用到Promise.all()方法,等执行完成里面的方法才会往下执行

模拟所述业务场景,创建三个异步函数,当做三个请求,每个请求时长一秒钟

function ajax1() {return new Promise((resolve, reject) => {setTimeout(() => {console.log("请求1的数据");resolve("请求1的数据");}, 1000);});
}
function ajax2() {return new Promise((resolve, reject) => {setTimeout(() => {console.log("请求2的数据");resolve("请求2的数据");}, 1000);});
}
function ajax3() {return new Promise((resolve, reject) => {setTimeout(() => {console.log("请求3的数据");resolve("请求3的数据");}, 1000);});
}

未使用Promise.all()所需时间:3011


const btn = document.getElementById("btn");
btn.addEventListener("click", async () => {console.log("开始执行");const start = Date.now();await ajax1();await ajax2();await ajax3();const end = Date.now() - start;console.log("执行结束,所用时间", end);
});

使用Promise.all()后,执行时间:1013,对比未使用,少了三倍

btn.addEventListener("click", async () => {console.log("开始执行");const start = Date.now();await Promise.all(ajax1(), ajax2(), ajax3());const end = Date.now() - start;console.log("执行结束,所用时间", end);
});

五、race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const promise = Promise.race([p1, p2, p3])

但不同的是,在p1,、p2、p3中谁最先返回的,那么这个promise状态就由它决定,返回值也是由它决定

例子,如果有一个Promise实例失败,那么结束了。

  • 比如三个人比赛跑步,谁先跑到终点,谁就能拿到金牌,拥有金牌的所有权

代码演示

依旧是模拟三个请求,但是设置不同的请求时长

function ajax1() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求1");}, 1000);});
}
function ajax2() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求2");}, 2000);});
}
function ajax3() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求3");}, 3000);});
}

使用方法

const btn = document.getElementById("btn");
btn.addEventListener("click", () => {console.log("开始执行");const p = Promise.race([ajax1, ajax2, ajax3]);p.then((res) => {console.log("谁是金牌:", res);});console.log("执行结束");
});

六、allSettled

Promise.allSettled()也是将多个Promise实例包装成一个新的Promise实例,但不同的是,它会等这些Promise实例都执行结束,无论状态是成功还是失败,包装实例才会结束。

返回结果由多个Promise实例结果组成

业务场景

  • 不关心请求返回的结果,只关心请求是否完成
function ajax1() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求1");}, 1000);});
}
function ajax2() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求2");}, 2000);});
}
function ajax3() {return new Promise((resolve, reject) => {setTimeout(() => {resolve("请求3");}, 3000);});
}const btn = document.getElementById("btn");
btn.addEventListener("click", () => {console.log("开始执行");const p = Promise.allSettled([ajax1, ajax2, ajax3]);p.then((res) => {console.log("结果", res);});console.log("执行结束");
});

七、any

Promise.any()也是接收一组Promise实例作为参数,然后返回一个新的Promise实例,它与race有些类似,但它不会因为一个Promise实例失败就结束。

const p = Promise([p1, p2, p3])

一组Promise实例中,只要有一个Promise实例成功,那么包装实例的状态就是成功的;如果所有参数Promise实例都失败,那么包装实例就是失败的

只要一个成功,那么包装实例就是成功的,返回结果由最先成功的Promise实例决定

function ajax1() {return new Promise((resolve, reject) => {resolve("成功请求1");});
}
function ajax2() {return new Promise((resolve, reject) => {resolve("成功请求2");});
}
function ajax3() {return new Promise((resolve, reject) => {resolve("成功请求3");});
}const btn = document.getElementById("btn");
btn.addEventListener("click", () => {console.log("开始执行");const p = Promise.any([ajax1, ajax2, ajax3]);p.then((res) => {console.log("结果", res);});console.log("执行结束");
});

所有都失败,包装实例才是失败的,返回结果由最先失败的Promise实例决定

function ajax1() {return new Promise((resolve, reject) => {reject("请求1");});
}
function ajax2() {return new Promise((resolve, reject) => {reject("请求2");});
}
function ajax3() {return new Promise((resolve, reject) => {reject("请求3");});
}const btn = document.getElementById("btn");
btn.addEventListener("click", () => {console.log("开始执行");const p = Promise.any([ajax1, ajax2, ajax3]);p.then((res) => {console.log("结果", res);});console.log("执行结束");
});

这篇关于Promise学习之基本方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1105464

相关文章

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

如何将Python彻底卸载的三种方法

《如何将Python彻底卸载的三种方法》通常我们在一些软件的使用上有碰壁,第一反应就是卸载重装,所以有小伙伴就问我Python怎么卸载才能彻底卸载干净,今天这篇文章,小编就来教大家如何彻底卸载Pyth... 目录软件卸载①方法:②方法:③方法:清理相关文件夹软件卸载①方法:首先,在安装python时,下

电脑死机无反应怎么强制重启? 一文读懂方法及注意事项

《电脑死机无反应怎么强制重启?一文读懂方法及注意事项》在日常使用电脑的过程中,我们难免会遇到电脑无法正常启动的情况,本文将详细介绍几种常见的电脑强制开机方法,并探讨在强制开机后应注意的事项,以及如何... 在日常生活和工作中,我们经常会遇到电脑突然无反应的情况,这时候强制重启就成了解决问题的“救命稻草”。那

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

Python Transformer 库安装配置及使用方法

《PythonTransformer库安装配置及使用方法》HuggingFaceTransformers是自然语言处理(NLP)领域最流行的开源库之一,支持基于Transformer架构的预训练模... 目录python 中的 Transformer 库及使用方法一、库的概述二、安装与配置三、基础使用:Pi

关于pandas的read_csv方法使用解读

《关于pandas的read_csv方法使用解读》:本文主要介绍关于pandas的read_csv方法使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录pandas的read_csv方法解读read_csv中的参数基本参数通用解析参数空值处理相关参数时间处理相关

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob