自学前端Promise的理解和应用,好程序员分享Promise模式实现

2023-05-28 0 818

原副标题:自修后端Promise的认知和应用领域,好开发人员撷取Promise商业模式同时实现

一、Promise小白怎么用?从四个故事情节已经开始吧

1、嘿嘿几段专业名词故事情节

您是一位在有名沉沦城市中历险的盖基。您置身于一家点缀绚丽的卧室中,四面满布了有名的雕塑和浮雕。您发现有四个地下通道依次通往不同的路径,依次是:四个邪恶的地下通道和四个光亮的地下通道。

邪恶的地下通道中充满著了谜样的韵味,您能感受到当中蕴含着的有名精神力量。您无人知晓它会带您去这儿,但您能感受到当中蕴含的脆弱和未明。再者,光亮的地下通道看上去凉爽宽敞,您能看到高处映照的日光。您能听见许多嘹亮的翩翩起舞,或许在那个路径上有许多人在庆祝。

现在,您需要在这四个地下通道之间作出优先选择。您会选择哪四个地下通道呢?您的优先选择Sonbhadra影响您接下去的历险之旅。

2、再来看几段谜样的小记录片

https://drive.weixin.qq.com/s?k=AOoAUwfiAAwVgJbsSaAUEA_QbjAFk

3、很久了还不进入自问自答

嘿嘿介绍两个单字,两个Promise的名词

● Promise的四个状况:pending(等候状况)、fulfilled(已获得成功状况)和 rejected(已失利状况)

● Promise的四个常见反弹表达式(咱说的是常见):

1. 示例化第一类时传至的反弹表达式

2. then方式的传至的四个反弹表达式

3. catch方式传至的四个反弹表达式

以工作台为例,继续深入细致介绍Promise

1、已经开始写工作台,这时Promise状况为pending,我们能认知为初始状况,也能认知为销售业务处置中

2、工作台完成情况有三种,一类是完稿了,一类是被狗吃了

3、无论哪种情况,必须要告诉老师,获得成功了就通过resolve地下通道暂存数据,同时会更改状况为获得成功fulfilled;失利了就通过reject地下通道暂存数据,同时修改状况为rejected。

5、简单来几段代码看看

const p = new Promise(function (resolve, reject) {

resolve(通过获得成功地下通道存储数据)

})

//…如果不使用then,提取,则数据一直暂存在p第一类中

//提取结果

p.then(function (val) {

console.log(val)

})

6、这些写法都是固定的,建议使用promise之前一定要充分介绍反弹表达式

7、咱们再升级一下,写工作台用了5秒钟

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

//写工作台用了5秒钟,5秒钟之后,把获得成功的工作台暂存到resolve地下通道中

setTimeout(() => {

resolve(这是工作台)

}, 5000)

})

//上面代码中调用了resolve的时候,then里面的反弹表达式才会触发,这里有个时间差或者时空差的感觉

p1.then(function (val) {

console.log(val)

})

8、再升级一下,这工作台他也有被狗吃了的时候,我们假定5秒钟之外就被狗吃了,5秒钟之内就是完成的

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

//生成一个1~6秒之间的随机数

const time = Math.random() * 4000 + 2000

setTimeout(() => {

if (time <= 5000) {

resolve(获得成功交作业啦)

} else {

reject(`工作台被狗吃了,耗费了${time秒}`)

}

}, time)

})

//获得成功使用then来接,失利了怎么拿到参数呢?

//用then的第二个参数来拿失利的参数

p2.then(function (val) {

console.log(val)

}, function (err) {

console.log(估计是被狗吃了, err)

})

9、除了then的第二个参数能拿到失利的结果,还能通过catch方式拿到结果,一会再讨论这三种用法的区别,先看catch的用法,注意这里需要连用

p2.then(function (val) {

console.log(val)

}).catch((reason) => {

//输出失利原因,大概率是被狗吃了

console.log(估计是被狗吃了, reason)

})

10、再看一类常见的连用的写法

new Promise(function (resolve, reject) {

//生成四个1~6秒之间的随机数

const time = Math.random() * 4000 + 2000

setTimeout(() => {

if (time <= 5000) {

resolve(获得成功交工作台啦)

} else {

reject(`工作台被狗吃了,耗费了${time}秒`)

}

}, time)

}).then(function (val) {

console.log(val)

}).catch((reason) => {

//输出失利原因,大概率是被狗吃了

console.log(估计是被狗吃了, reason)

})

11、许多需注意的地方

1. resolve和reject只是四个形参的名字,对应实际的值是promise内部的表达式,调用这四个其实调用的就是promise内部的某个表达式而已,这个名字能随便去改,例如

new Promise(function (ok, fail) {

//这时此刻形参叫ok,但实际代表的是promise内部表达式

ok(ojbk)

}).then((res) => {

//promise内部会存储数据,传给res这个变量,这时res 值就是ojbk

console.log(res)

})

2. new Promise(构造器的参数是四个表达式),这个表达式会同步执行,代码执行到这里的时候就会立即执行

12、小结

1. Promise通过构造表达式同步执行,执行结果调用promise的内部表达式存储,通常叫resolve和reject,四个是获得成功时存储存储使用的地下通道,另四个是失利时存储的地下通道,无论存储到哪个地下通道中,都是写代码的人去定义的

2. then有四个参数,依次是四个表达式类型的参数,第四个参数是在调用resolve时会触发,第二个参数是在调用reject时触发

3. catch方式能替代then的第二个参数,拿到reject结果

13、附赠then第二个参数和catch的区别

在then的第四个参数里面的代码,如果出现异常的时候,不用手动的try…catch,通过promise示例第一类的.catch能捕获then内出现的异常,但注意,catch不会捕获构造表达式代码中的错误,来看例子

new Promise(function (ok, fail) {

setTimeout(() => {

//故意5秒后触发k的报错

console.log(k)

}, 5000)

}).then((res) => {

console.log(res)

}).catch(error => {

//这个时候,error是拿不到那个错误的,他不负责console.log(k)所在代码块中出现的错误

console.log(error)

})

自学前端Promise的理解和应用,好程序员分享Promise模式实现

再看四个catch方式能捕获什么地方的错误

自学前端Promise的理解和应用,好程序员分享Promise模式实现

大概就是这么个大概

二、为什么要这么用,图个啥~

使用 Promise 的主要原因是他可以解决反弹地狱(反弹嵌套)问题,让代码变得更优雅,逻辑更清晰

举四个生活中的例子,早上起床第一件事是要穿拖鞋,第二件事是洗漱,第三件事是穿衣服,第四件事是查看“身手要钱”,第五件事是打开自家房门出去开车上班,每件事都需要串行,每一步与下一步都有关联关系

function foo() {

//1、穿拖鞋已经开始

setTimeout(() => {

//1、2秒后穿拖鞋完成

//2、洗漱已经开始

setTimeout(() => {

//2、2秒后洗漱完成

//3、穿衣服已经开始

setTimeout(()=>{

//3、穿衣服完成

//….不好意思看官,后边还有好两个步骤咱就意思一下,再写就吐了

},2)

}, 2)

}, 2)

}

foo()

就写这几层吧,是不是太恶心了

new Promise((resolve, reject) => {

//1、穿拖鞋

setTimeout(() => {

resolve(穿拖鞋搞定)

}, 2000)

}).then(val => {

//等候穿拖鞋完成后,会调用这个表达式

//2、洗漱

//注意此处!!!,必须使用return 返回四个新的promise来完成链式调用

const p = new Promise((resolve, reject) => {

setTimeout(() => {

resolve(洗漱搞定)

}, 2000)

})

return p

}).then(val => {

//3、穿衣服,此处直接返回,没有使用中间变量

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve(穿衣服搞定)

}, 2000)

})

}).then(val => {

//4、查看“身手要钱”

return new Promise((resolve, reject) => {

setTimeout(() => {

resolve(查看“身手要钱”搞定)

}, 2000)

})

}).then(val => {

//5、开车去上班

// 元气满满的一天

})

就图这~

三、Promise其他方式

那么多方式,不讲那么多,race、all什么的网上一抓一大把

说说语法糖await和async的用法

先介绍四个基础规则

● await必须修饰的是Promise第一类

● await必须在async中使用

● await只能接收resolve地下通道的结果,reject结果会导致报错

● await修饰的代码在执行时,代码是卡住的,类似于alert,这句代码不执行完,后边的代码不会向下执行,这也类似于线程同步执行的概念,这也是await有用之处

● async修饰的必须是表达式

● async修饰后的表达式在执行之后会转为Promise第一类

看几段简单的代码

async function foo() {

let k = await new Promise(function (resolve, reject) {

setTimeout(() => {

resolve(qfedu)

}, 2000)

})

console.log(k)

}

foo()

这样用倒是更麻烦,我们把要处置的事黏黏糊糊多弄许多试一试

async function foo() {

let level1 = await new Promise((resolve, reject) => {

//1、穿拖鞋

setTimeout(() => {

resolve(穿拖鞋搞定)

}, 1000)

})

//拿着第一步的结果,去第二步进行操作

let level2 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level1 + 洗漱搞定)

}, 1000)

})

let level3 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level2 + 穿衣服搞定)

}, 1000)

})

let level4 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level3 + 查看“身手要钱”搞定)

}, 1000)

})

console.log(level4 + ,之后开车去上班,元气满满的一天)

}

foo()

输出结果:

这样代码看上去更加简洁,当然要重点考虑的问题是在整个从上到下的调用过程中,任何四个环节出现问题,都会影响下面的代码

再来,我们把代码聚焦到foo()方式调用之前和调用之后

console.log(1)

foo() //这个会输出 穿拖鞋搞定洗漱搞定穿衣服搞定查看“身手要钱”搞定……等

console.log(2)

思考一下,程序输出的顺序

注意,使用async包裹的代码,属于异步代码,会在同步代码之后执行

我们给按钮添加四个点击事件,看点击按钮如何让程序使用await顺序执行

async function foo() {

let level1 = await new Promise((resolve, reject) => {

//1、穿拖鞋

setTimeout(() => {

resolve(穿拖鞋搞定)

}, 1000)

})

//拿着第一步的结果,去第二步进行操作

let level2 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level1 + 洗漱搞定)

}, 1000)

})

let level3 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level2 + 穿衣服搞定)

}, 1000)

})

let level4 = await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(level3 + 查看“身手要钱”搞定)

}, 1000)

})

console.log(level4 + ,之后开车去qfedu上班,元气满满的一天)

}

window.onclick = foo;

//或者是

window.onclick = async function(){

//todo …

//await new Promise…

//await new Promise…

//await new Promise…

//…

}

实际场景中,await 与async通常见来处置ajax请求类代码,让代码更简洁,再次强调,await只接收resolve结果,注意reject和error的错误要使用try…catch…处置异常。

今日的好程序员的撷取就到这里,想介绍更多,欢迎评论区探讨,或者dd小源~

相关文章

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

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