【javascript】迅速理清promise运行机制与实际中的应用

背景

  • 博主在网络上查了各种关于promise的资料,结果还是弄不懂到底怎么转化成实际当中的运用。网上的资料都是Promise写个settimout然后做例子。尼玛这谁都知道promise完后能.then运行,但一到具体场景就不会用了,顶多就是用人家本来就是Promise包装好的进行.then玩,真正自己包装不会。后来博主白嫖到一个讲Promise的视频,终于把这玩意理清楚了。真的是理解不了最好的方法就是找视频学,一个视频讲的不行找另一个。

Promise运行顺序

基本形式

  • 我个人认为以前不了解promise的真正原因是不了解运行顺序。虽然看别人文章大家都知道是成功运行resolve,失败运行reject,但还是蒙逼状态。所以,最先理解的应该是promise的运行顺序。
let p = new Promise(function(resolve,reject){
	$.ajax({
	url:'xxxxx',
	success(res){resolve(res)},
	err(res){reject(res)}	
	})
});
  • 首先看上面这种 基本形式,在p进行new Promise的时候,Promise函数体内的内容已经开始执行了,上面这个例子就是已经发送了ajax请求去了,然后回来的这个resolve和reject是需要在后面的.then当中定义,如果new 一个Promise后不.then,它就发一个请求就没了。
p.then(result=>{console.log(result)},msg=>{console.log(msg)})
  • 上面对p进行.then操作,then里面2个参数是2个function,实际是分别赋给了前面new Promise时里面那个function中的参数。也就是result=>{console.log(result)}给了p=new Promise(function(resolve,reject){})中的resolve。同理,msg那个函数当作参数给了reject。我觉得这句是理解关键。所以没有then只定义promise其实是不完整的。

链式调用

  • 我们都知道promise完后.then后还能.then,但是每个.then实际上它管的状态不是一个东西。拿上面那个例子举例,如果p发送ajax我们当作成功,那么他就会执行.then中的第一个参数function,如果这个function中有错,那么第二个.then会执行它的第二个参数function。所以也就是说.then返回的其实也是个Promise,并且下一个.then中它会判断前一个Promise也就是.then的执行是成功还是失败,如果成功,那么就走它第一个参数,失败走第二个参数。
  • 根据上面的性质,.then中的函数可以手动封装一个promise并return,这样就会让下一个.then等待这个Promise完成后执行。具体例子看后面的参数传递。

参数传递

  • 在第一个p.then中,如果.then里return了一个值,那么这个值就会作为参数传递给下一个.then,如果里面没有返回值,那么参数就是undefined
  • 有返回值的promise和没返回值的promise区别很大,看下面这个例子:
let a = function (){
  return  new Promise(function (resolve,reject) {
    setTimeout(() => {
        console.log(1);
        resolve()
    }, 1000);
  })
}

let b = function (){
    return new Promise(function(resolve,reject){
        setTimeout(() => {
            console.log(2);
            resolve()
        }, 1000);
    })
}

a().then(()=>b()).then(()=>{console.log('完成')});
a().then(()=>{b()}).then(()=>{console.log('二次完成')});
  • 我们封装了2个Promise,第一条语句是在a运行完后返回b,第二条是不返回b,最后输出结果是:

1
1
二次完成
2
2
完成

  • 可以发现,返回b的Promise后会等待Promise完成后执行,但是如果不返回Promise就会不等待b的执行直接进行下一个.then操作。

catch语句

  • 一般是不建议写reject的,因为Promise有catch语句,总写reject冗余,而且reject中的语句如果没有错误,那么下一个,then就会执行resolve而不是reject。
  • catch语句也是比较特殊的,我们看下面这个例子:
let a = function (){
  return  new Promise(function (resolve,reject) {
    setTimeout(() => { 
        console.log(1);
        reject()
    }, 1000);
  })
}

let b = function (){
    return new Promise(function(resolve,reject){
        setTimeout(() => {
            console.log(2);
           resolve()
        }, 1000);
    })
}

a().then(()=>b(),()=>2).then(()=> 5).then(()=>{console.log('sss1')}).catch(()=>{console.log("抓到错误1")})
a().then(()=>b()).then(()=> 5).then(()=>{console.log('sss2')}).catch(()=>{console.log("抓到错误2")})

1
1
sss1
抓到错误2

  • 我们把上面的例子修改了下,a变为失败走reject,那么实际上,如果没有写.then中的第二个function的话,后面的.then统统不会运行,导致catch能捕捉到错误。但是如果写了then中的第二个function,那么后面运行全都正确,catch是抓不到错误的。
  • 再看下一个例子
let a = function (){
  return  new Promise(function (resolve,reject) {
    setTimeout(() => { 
        console.log(1);
        resolve()
    }, 1000);
  })
}

let b = function (){
    return new Promise(function(resolve,reject){
        setTimeout(() => {
            console.log(2);
           reject()
        }, 1000);
    })
}
a().then(()=>b()).catch(()=>{console.log("抓到错误1")})
  • 前面我们把a中reject了,b中正常,这次调换一下,a中正常,b中reject。最后运行结果是能抓到错误。
  • 所以,这个catch,它可以抓到上一级错误和同级的.then的错误,相当于管了2层,但是更多层不行。

基本封装

  • 其实就是上面的例子,把要完成的异步操作做成一个function,这样异步操作不会立即执行,function会返回promise,这样等function调用时候,就相当于立即生成了个Promise,就可以立马进行.then操作了。

实际应用

  • 这个就是类似于上面操作,先封装各个异步操作,然后.then的时候return需要执行的下一个异步操作。参考上面参数传递的例子。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值