初识Promise

什么是promise?MDN官方文档的解释如下:

Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单点说,就是处理异步请求,我们经常会做些承诺,如果我赢了我就做A事情,如果输了我就做B事情。 这就是promise的中文含义:诺言,一个成功,一个失败。

那Promise在js中到底是个什么东西呢?看以下代码,可在浏览器中将其打印出来,如图:

通过prototype可以看出promise是一个构造函数。咱们先new一个promise看看能执行什么,代码如下:

new Promise(function(resolve,reject){
  console.log("1")
})

这段代码直接打印出了1,在这段代码中,Promise的参数是一个函数,这个函数有两个参数,resolve,reject,按照官方文档的说法,Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果的值

什么意思呢?就是promise这个值刚一定义出来,并不知道代码会是完成状态或是失败状态,所以Promise存在了三种状态:

  • pedding状态,这个状态不是成功也不是失败;
  • fullfiled状态,就是成功状态,想要达到这个状态需要调用resolve方法;
  • rejected状态,想要达到这个状态需要调用reject方法;

其中,状态只能由pedding变换为rejected或者fulldied,不可逆转。

转换图如下:

将上面的代码放在浏览器里面,就会直接执行,打印出1,所以我需要将它用一个函数包裹一下:

var p = new Promise(function(resolve,reject){
    console.log("1")
});

这样只需要在使用Promise时,调用这个函数就可以了。有人可能会问这有什么用,我直接实行console.log(1)不就行了,干嘛要包在Promise里面呢,什么鬼?这个需要回到Promise的作用上面来。

Promise的作用是什么?通俗的讲就是控制异步函数的调用。

上面的代码还不足以看出Promise的威力,只是告诉大家如何将Promise放到一个函数里面。

接着咱们按照文章开头举的是否嫁给我的例子来看一段代码:

function WeddingOrNot(){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(Math.random()-0.5>0){        
              resolve('你要嫁给我,咱们下一步去领证');
            }else{
              reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
            }
        }, 2000);
    });           
}
WeddingOrNot().then(function(data){
  console.log(data);
}).then(function(){
  console.log("买喜糖")
}).then(function(){
  console.log("发请柬")
}).then(function(){
  console.log('幸福的生活在一起')
}).catch(function(data){
  console.log(data);
  console.log('直接执行catch,所有的then都不会执行')
})

weddingornot是否结婚,是一个异步函数。是否结婚存在一个概率问题,这里用Math.random来计算:

  • 如果嫁给我,将结果传递给resolve,将Promise由pedding状态变换为fullfiled状态,后面紧跟的then方法中的function会得到传递出过来的数据,并且then链调用会同步一个一个逐步执行;
  • 如果不结婚,将结果传递给reject,后面的then一个都不会执行,直接跳到catch里面来执行。

分别看下执行结果如图:

或者

有兴趣的朋友可以自己测试一下。

假如结婚后中间出了一些状况离婚了,也需要直接跳到catch里面来,那要怎么实现呢,看代码:

function WeddingOrNot(){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(Math.random()-0.5>0){        
              resolve('你要嫁给我,咱们下一步去领证');
            }else{
              reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
            }
        }, 2000);
    });           
}
WeddingOrNot().then(function(data){
  console.log(data);
}).then(function(){
  console.log("买喜糖")
}).then(function(){
  console.log("发请柬")
}).then(function(){
  return new Promise(function(resolve,reject){
    
    if(Math.random()-0.5>0){ 
              console.log("经历了诱惑,没有出轨,继续在一起")       
              resolve('经历了诱惑,没有出轨,继续在一起');
            }else{
              reject("有人出轨,婚姻到此结束了,直接执行catch")
            }

  })
}).then(function(){
  console.log('幸福的生活在一起')
}).catch(function(data){
  console.log(data);
  console.log('直接执行catch,所有的then都不会执行')
})

读代码,在发请柬幸福的生活在一起之间咱们插入了一个then,里面的函数呢返回了一个Promise实例,并且这个实例会变为rejected或者fullfiled状态,并将结果传递出去。看下运行结果:

或者

可以看出,在then链的调用中,某个then返回另外一个promise实例,且也是按照随机数来变换promise的状态的。如果调动了reject,幸福生活在一起也不会执行,那这有是没用呢,刚才的判断出轨是同步执行的将其替换为异步执行测试一下,代码如下:

function WeddingOrNot(){
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            if(Math.random()-0.5>0){        
              resolve('你要嫁给我,咱们下一步去领证');
            }else{
              reject('你不会嫁给我,后面的不需要执行了,咱们到此结束,')
            }
        }, 2000);
    });           
}
WeddingOrNot().then(function(data){
  console.log(data);
}).then(function(){
  console.log("买喜糖")
}).then(function(){
  console.log("发请柬")
}).then(function(){
  return new Promise(function(resolve,reject){
    setTimeout(function(){
      if(Math.random()-0.3>0){
        console.log('经历了诱惑,没有出轨,继续在一起')        
              resolve('经历了诱惑,没有出轨,继续在一起');

            }else{
              reject("有人出轨,婚姻到此结束了,直接执行catch")
            }
    },1000)
  })
}).then(function(){
  console.log('幸福的生活在一起')
}).catch(function(data){
  console.log(data);
  console.log('直接执行catch,所有的then都不会执行')
})

来看执行结果:

或者

或者

代码照样会按照你设计的then链逐步调用——这就是promise的威力。

关于结婚不结婚这个案例,如果不用promise实现会是什么样呢,看代码:

function xingfu(){
  console.log("幸福的生活在一起")
}
function lihun(){
  console.log("离婚了")
}
setTimeout(function(){
  if (Math.random()-0.5>0) {
    console.log("结婚继续往下走");
    console.log("买喜糖")
    console.log("发请柬");
    setTimeout(function(){
      if (Math.random()-0.3>0) {
        console.log("经历了诱惑继续在一起")
        xingfu();
      } else {
        console.log('有人出轨了,结束了')
        lihun()
      }
    },300)
  } else {
    lihun()
  }
},300)

运行结果大家自己去测试,这里就不贴图了。

可以看到,这段代码的组织结构产生了回调嵌套,组织代码顺序完全不如用promise实现看着顺眼。当然有的朋友会说:一个两个嵌套而已,还好。

那如果嵌套三个,四个,五个......想象一下。

promise还有一些很有意思的用法,不是一篇文章能讲完的,咱们下次继续。

有疑问可给此公众号发送信息。

欢迎转发!

原文发布于微信公众号 - nodejs全栈开发(geekclass)

原文发表时间:2017-11-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券