原副标题:自修后端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)
})
再看四个catch方式能捕获什么地方的错误
大概就是这么个大概
二、为什么要这么用,图个啥~
使用 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小源~