Promise的理解和使用

2022-12-30 0 1,010

Promise是甚么?

认知

抽象化抒发

Promise是两门捷伊技术(ES6规范)Promise是JS中展开触发器程式设计的新软件系统

附注:旧的计划是纯粹采用反弹表达式

具体内容抒发

从句法上而言:Promise是两个内部结构

Promise第一类的状况发生改变

Promise的状况指的是示例第一类中的两个特性PromiseState,它的值有四个:

pending:未下定决心的resolve/fulfilled:获得成功rejected:失利

Promise的状况发生改变多于上面的四种情形:

由pending转变成resolved由pending转变成rejected放出极度:假如现阶段为pending就会转变成rejected

表明:多于这2种,且两个Promise第一类根本无法发生改变一场,不论转变成获得成功却是失利,单厢有两个结论统计数据,获得成功的结论统计数据通常称作value,失利的结论统计数据通常称作reason。

Promise第一类结论值特性

Promise示例第一类中除了两个特性PromiseResult,留存着第一类获得成功/失利的结论。要想发生改变它的值,多于透过给resolve()或是reject()方式传参,获得成功时,将相关联统计数据传至resolve()方式,失利时,将相关联的统计数据传至reject()方式,后能在then(value => {}, reason => {})方式中抽出,value相关联着resolve()转交的模块,reason相关联着reject()转交的模块。

Promise的基本上采用

市场需求:点选按键,1秒后表明与否中大奖(30%机率中大奖)。若中大奖,弹出:恭贺恭贺,礼品为10万RMB宾利代金券;若未中大奖弹出:奋力拼搏。

html网页,放个副标题和按键方可:

<h2>Promise 全唇兰</h2> <button>点选抽奖</button>

不采用Promise的js代码:

<script> // 生成随机数 function rand(m, n) { return Math.ceil(Math.random() * (n m + 1) + m 1); } /** 市场需求: * 点选按键, 2s 后表明是否中大奖(30%机率中大奖) * 若中大奖,弹出:恭贺恭贺,礼品为 10万 RMB 宾利代金券 * 若未中大奖弹出: 奋力拼搏 */ // 旧的方式 const btn = document.querySelector(button); // 绑定单击事件 btn.addEventListener(click, function () { // 定时器 setTimeout(() => { // 30% 中大奖机率,如果数字为1—100,那么我们随机数小于30,就认为它中大奖了(简易的算法) let n = rand(1, 100); // 判断 if (n <= 30) { alert(恭贺恭贺,礼品为 10万 RMB 宾利代金券); } else { alert(奋力拼搏); } }, 1000); }) </script>

采用Promise,js代码:

<script> // 生成随机数 function rand(m, n) { return Math.ceil(Math.random() * (n m + 1) + m 1); } const btn = document.querySelector(button); // 绑定单击事件 btn.addEventListener(click, function () { // Promise 形式实现 // resovle 解决 是表达式类型的统计数据 触发器任务获得成功时调用 // reject 拒绝 是表达式类型的统计数据 触发器任务失利时调用 let p = new Promise((resolve, reject) => { setTimeout(() => { // 30% 中大奖机率,假如数字为1—100,那么我们随机数小于30,就认为它中大奖了 let n = rand(1, 100); // 判断 if (n <= 30) { resolve(); // 将 promise 第一类的状态设置为 获得成功 } else { reject(); // 将 promise 第一类的状况设置为 失利 } }, 1000); }); // 调用 then 方式 // then方式的第两个反弹表达式,promise第一类状态为获得成功时调用,第二个反弹表达式,promise第一类状况为失利时调用 p.then(() => { alert(恭贺恭贺,礼品为 10万 RMB 宾利代金券); }, () => { alert(奋力拼搏); }) }) </script>

现在市场需求变更,在弹出提示时,同时告知本次抽到的数字。

不采用Promise的js代码:

<script> // 生成随机数 function rand(m, n) { return Math.ceil(Math.random() * (n m + 1) + m 1); } // 旧的方式 const btn = document.querySelector(button); // 绑定单击事件 btn.addEventListener(click, function () { // 定时器 setTimeout(() => { // 30% 中大奖机率,假如数字为1—100,那么我们随机数小于30,就认为它中大奖了 // let n = rand(1, 100); // 判断 if (n <= 30) { alert(恭贺恭贺,礼品为 10万 RMB 宾利代金券,您的中大奖数字为: + n); } else { alert(奋力拼搏,您抽中的数字为: + n); } }, 1000); }) </script>

采用Promise的js代码:

<script> // 生成随机数 function rand(m, n) { return Math.ceil(Math.random() * (n m + 1) + m 1); } const btn = document.querySelector(button); // 绑定单击事件 btn.addEventListener(click, function () { // 假如现在需要在弹出提示时,同时告知本次的号码,该怎么办? // 只需要将获得成功或失利的值分别传至 resolve() 和 reject() 方式,然后再then()方式的两个反弹表达式中转交方可。 let p = new Promise((resolve, reject) => { setTimeout(() => { // 30% 中大奖机率,假如数字为1—100,那么我们随机数小于30,就认为它中大奖了 let n = rand(1, 100); // 判断 if (n <= 30) { resolve(n); // 将 promise 第一类的状况设置为 获得成功 } else { reject(n); // 将 promise 第一类的状况设置为 失利 } }, 1000); }); // 调用 then 方式 // then方式的第两个反弹表达式,promise第一类状况为获得成功时调用,第二个反弹表达式,promise第一类状况为失利时调用 // value 值 // reason 理由 p.then((value) => { alert(恭贺恭贺,礼品为 10万 RMB 宾利代金券,您的中大奖数字为: + value); }, (reason) => { alert(奋力拼搏, 您的号码为: + reason); }) }) </script>

Promise的基本上流程

Promise的理解和使用

为甚么要采用Promise?

指定反弹表达式的方式更加灵活

旧的:必须在启动触发器任务前指定promise:启动触发器任务=> 返回promise第一类=>给promise第一类绑定反弹表达式(甚至能在触发器任务结束后指定两个或多个)

支持链式调用,能解决反弹地狱问题

甚么是反弹地狱?

反弹表达式嵌套调用,外部反弹表达式触发器执行的结论是嵌套的反弹执行的条件

例如,上面的代码是Node.js的fs模块读取四个文件,并将读取到的结论展开拼接并且输出到控制台中。

fs.readFile(./resource/1.txt, (err, data1) => { if (err) throw err; fs.readFile(./resource/content.txt, (err, data2) => { if (err) throw err; fs.readFile(./resource/2.txt, (err, data3) => { if (err) throw err; console.log(data1 + data2 + data3); }) }) })

这个代码片段,fs.readFile()在嵌套调用,这里就形成了反弹地狱。

反弹地狱的缺点

不便于阅读不便于极度处理

软件系统?

采用promise链式调用,

终极软件系统:async/await

如何采用Promise?

API

Promise内部结构表达式

Promise的内部结构表达式:Promise(executor){}

executor表达式:执行器(resolve, reject) => {}resolve表达式:内部定义获得成功时我们调用的表达式reject表达式:内部定义失利时我们调用的表达式

表明:executor会在Promise内部立即同步调用,触发器操作在执行器中执行。

Promise.prototype.then方式

Promise.prototype.then方式:(onResolved, onRejected) => {}

onResolved表达式:获得成功的回调表达式,通常这么写: value => {}onRejected表达式:失利的反弹表达式,通常这么写reason => {}

表明:指定用于得到获得成功value的获得成功反弹和用于得到reason的失利反弹,返回两个捷伊Promise第一类。

Promise.prototype.catch方式

Promise.prototype.catch方式:(onRejected) => {}

onRejected表达式:失利的回调表达式,通常这么写reason => {}

catch()根本无法指定失利的反弹,不能指定获得成功的反弹。其实也是采用then()实现的.

表明:catch()是 then()的句法糖, 相当于: then(undefined, onRejected) 。

Promise.resolve方式

Promise.resolve方式:(value) => {}

value:获得成功的统计数据或Promise第一类

表明:返回两个获得成功/失利的Promise第一类

catch()方式和resolve()方式的采用:

<script> // 假如传至的模块为 非Promise类型的第一类,返回的结论为 获得成功的Promise第一类 // 假如传至的参数为 Promise第一类,则模块的结论下定决心了resolve的结论 let p1 = Promise.resolve(555); console.log(p1); // Promise {<fulfilled>: 555} let p2 = Promise.resolve(new Promise((resolve, reject) => { resolve(OK); })); console.log(p2); // Promise {<fulfilled>: “OK”} // 传至失利的Promise let p3 = Promise.resolve(new Promise((resolve, reject) => { reject(Error); })); console.log(p3); // Promise {<rejected>: “Error”} // 失利的同时还报错了,原因是没有对错误展开处理,这里采用catch()展开处理就能解决报错 p3.catch(reason => { console.log(reason); // Error }) </script>

Promise.reject方式

Promise.reject方式:(reason) => {}

reason:失利的原因

表明:返回两个失利的Promise第一类

reject()方式的示例:

<script> // 总结,Promise.reject()方式,不论你传至甚么得到的都是失利的Promise第一类,并且失利的结论就是你传至的模块。 let p = Promise.reject(555); console.log(p); let p2 = Promise.reject(hello); console.log(p2); let p3 = Promise.reject(new Promise((resolve, reject) => { resolve(OK); })) console.log(p3); </script>

Promise.all方式

Promise.all方式:(promises) => {}

promises模块:包含n个Promise第一类的数组

表明:返回两个捷伊Promise第一类,多于所有的Promise都获得成功才获得成功,只要有两个失利了就直接失利,失利的结论就是失利的Promise第一类的结论。

all()方式的示例:

<script> let p1 = new Promise((resolve, reject) => { resolve(OK); }); let p2 = Promise.resolve(Success); let p3 = Promise.resolve(Oh Yeah); let result1 = Promise.all([p1, p2, p3]); console.log(result1); // 返回两个获得成功的Promise第一类,第一类的结论是两个数组,数组中存有四个获得成功的promise第一类的结论 // 假如数组中 p2 是两个失利的Promise,那么all()方式返回的是两个失利的Promise第一类,并且失利的结论是数组中失利的Promise第一类的结论。 p2 = Promise.reject(Error); let result2 = Promise.all([p1, p2, p3]); console.log(result2); </script>

Promise.allSettled方式

Promise.allSettled方式:(promises) => {}

promises模块:包含n个Promise第一类的数组

表明:该方式返回的结论总是状况为获得成功的Promise第一类,这个Promise第一类的结论值是包含promises模块中每两个promise第一类的状况以及结论值的第一类数组。

注意和all()方式的区别。

allSettled()方式示例:

<script> // 声明两个Promise第一类 let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(商品统计数据 – 1); // reject(ERROR) }, 1000); }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { // resolve(商品统计数据 – 2); reject(出错了); }, 1000); }) // 调用allSettled() 方式 该方式返回的结论总是获得成功的Promise第一类, // 它的结论值是包含每两个promise第一类的状况以及结论值的第一类。 let result = Promise.allSettled([p1, p2]); console.log(result); let res = Promise.all([p1, p2]); // 全部获得成功,才会返回获得成功的Promise第一类 console.log(res); </script>

Promise.race方式

Promise.race方式:(promises) => {}

promises模块:包含n个Promise第一类的数组

表明:返回两个捷伊Promise第一类,第两个完成的Promise第一类的结论状况就是最终的结论状况

race()方式的示例:

<script> // 同步代码 let p1 = new Promise((resolve, reject) => { resolve(OK); }) let p2 = Promise.resolve(Success); let p3 = Promise.resolve(Oh Yeah); // 调用 let result1 = Promise.race([p1, p2, p3]); // 代码从上往下执行,所以p1最先执行,所以result的状况和结论应该是p1的状况和结论。 console.log(result1); // 触发器代码 let p4 = new Promise((resolve, reject) => { setTimeout(() => { resolve(OK); }, 2000); }) let p5 = Promise.reject(Error); let p6 = Promise.resolve(Oh Yeah); let result2 = Promise.race([p4, p5, p6]); // p4为触发器代码,p5 会先于p4、p6执行,所以p5的状况和结论即为result2的状况和结论。 console.log(result2); </script>

Promise的几个关键问题

如何发生改变Promise的状况?

发生改变Promisede状况有四种方式:

resolve(value):假如现阶段是pending就会改转变成resolved(fulfilled)reject(reason):假如现阶段是pending就会转变成rejected放出极度:假如现阶段是pending就会转变成rejected

示例:

<script> let p = new Promise((resolve, reject) => { // 1. resolve表达式 // resolve(OK); // pending => fulfilled(resolved) // 2. reject 表达式 // reject(Error); // pending => rejected // 3. 放出错误 // throw 出问题了; // pending => rejected }) console.log(p); </script>

两个Promise指定多个获得成功/失利的反弹表达式,单厢调用吗?

指定反弹用的就是then(),所以这个题目的意思是假如采用then()方式为两个promise对象指定多个反弹,那么这些反弹与否单厢执行?

答案是:当Promise改转变成相关联状况时单厢调用。

示例:

<script> let p = new Promise((resolve, reject) => { resolve(OK); }) // 指定反弹 – 1 p.then(value => { console.log(value); }) // 指定反弹 – 2 p.then(value => { alert(value); }) // 有弹框,控制台有输出,表明这两个反弹都执行了。 </script>

发生改变Promise状况和指定反弹表达式谁先执行谁后执行?

都有可能,正常情形下是先指定反弹再发生改变状况,但也能先发生改变状况再指定反弹如何先改状况再指定反弹?在执行器中直接调用resolve()/reject()then()方式延迟更长时间才被调用

3. 甚么时候才能得到统计数据?

假如先指定的反弹,那当状况发生发生改变时,反弹表达式就会调用,得到统计数据假如先发生改变的状况,那当指定反弹时,反弹表达式就会调用,得到统计数据

示例:

<script> let p = new Promise((resolve, reject) => { // setTimeout(() => { // 触发器任务 resolve(OK); // 同步任务 // }, 1000) }) p.then(value => { console.log(value); }, reason => { }) // 1. 当Promise内部结构表达式中的executor执行器表达式内部是同步任务时,先发生改变状况,在执行then()方式指定反弹(注意是指定反弹,不是执行反弹) // 2. 当Promise内部结构表达式中的executor执行器表达式内部是触发器任务时,那么是先执行then()方式指定反弹表达式,再发生改变状况。 </script>

promise.then()返回新promise的结论状况由甚么下定决心?

简单抒发:由then()指定的反弹表达式执行的结果下定决心 详细抒发:假如放出极度, 新promise转变成rejected,reason为放出的极度 假如返回的是非promise的任意值,新promise转变成resolved,value为返回的值假如返回的是另两个新promise,此promise的结论就会成为新promise的结论

示例:

<script> let p = new Promise((resolve, reject) => { resolve(OK); // reject(error) }) // 执行 then 方式 let result = p.then(value => { // p 为获得成功的反弹 // console.log(value); // result的状况为fulfilled,结论为undefined,因为没有返回值 // 1. 放出错误 // throw 出了问题; // result 的状况为rejected,结论为出了问题 // 2. 返回结论为非 Promise 类型的第一类 // return 555; // result的状况为fulfilled,结论为555 // 3. 返回结论是Promise第一类 return new Promise((resolve, reject) => { // resolve(success); // result的状况为fulfilled,结论为success // reject(error); // result 的状况为rejected,结论为error throw 出了问题; // result 的状况为rejected,结论为出了问题 }) }, reason => { // p 为失利的反弹 // console.log(reason); // result的状况为fulfilled,结论为undefined,因为没有返回值。 这里本身会输出error // 1. 放出错误 // throw 出了问题; // result 的状况为rejected,结论为出了问题 // 2. 返回结论为非 Promise 类型的第一类 // return 555; // result的状况为fulfilled,结论为555 // 3. 返回结论是Promise第一类 return new Promise((resolve, reject) => { // resolve(success); // result的状况为fulfilled,结论为success // reject(error); // result 的状况为rejected,结论为error // throw 出了问题; // result 的状况为rejected,结论为出了问题 }) }) console.log(result); </script>

promise如何串连多个操作任务?

promise的then()返回两个捷伊promise,能继续调用then()方式,形成链式调用透过then的链式调用串连多个同步或触发器任务

示例:

<script> let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(OK); }, 1000); }) p.then(value => { return new Promise((resolve, reject) => { resolve(success); }) }).then(value => { console.log(value) // success }).then(value => { console.log(value) // undefined }) </script>

promise极度穿透?

当采用promise的then链式调用时,能在最后指定失利的反弹前面任何操作除了极度,单厢传到最后失利的反弹中处理
<script> let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(OK) // reject(Err) }, 1000); }) p.then(value => { // console.log(111); throw 出问题了; }).then(value => { // 也能在这里处理上面出现的错误 console.log(222) }).then(value => { console.log(333) }).catch(reason => { // 这里采用catch,也能采用then console.warn(reason); }) // 在调用链的最后指定失利的反弹,就能处理任务当中出现的错误,这个现象称作极度穿透。 </script>

如何中断promise链?

当采用promise的then链式调用时,想要在中间中断,不再调用后面的反弹表达式,有且多于两个办法:在反弹表达式中返回两个pending状况的promise第一类。

<script> // 假如想要中断这个then调用链,有且多于两个方式,在需要中断的反弹表达式中,返回两个pending状况的promise第一类 let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(OK); }, 1000); }) p.then(value => { console.log(111); // 假如后面不想让它调用了,有且仅有两个方式:返回两个pending状况的promise第一类 return new Promise(() => {}); }).then(value => { console.log(222) }).then(value => { console.log(333) }).catch(reason => { console.warn(reason); }) </script>

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务