对Promise的认识

导读:本篇文章讲解 对Promise的认识,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、Promise是什么?

  • ECMAscript 6 原生提供了 Promise 对象

  • 采用console.log(Promise)看一下它的结构组成
    UFF8TH.png

可以看出,Promise是一个构造函数;
它有resolve,reject,race等静态方法;
它的原型(prototype)上有then,catch方法;
因此只要作为Promise的实例,都可以共享并调用Promise.prototype上面的方法(then,catch)


二、Promise的使用

Promise的使用语法

new Promise(function(resolve,reject){}/**excutor**/);

在实例化Promise时需要传入一个函数excutor作为参数,
并且在Promise构造函数执行时同步执行

  • 实例1
new Promise((resolve,reject)=>{
    // 定时器,1秒后执行
  setTimeout(()=>console.log("执行操作"),1000);
})

可以看出1秒后,在控制台输出了相应结果,这说明:
在实例化Promise对象的过程中,作为参数的excutor函数也会执行

excutor函数还有两个参数resolve和reject,
其实这两个参数也是函数,在excutor执行时被调用

三、resolve和reject的具体用法

0. 首先我们来看看Promise的几种状态

  • pending: 初始状态,成功或失败状态
  • fulfilled: 意味着操作成功完成
  • rejected: 意味着操作失败
  • 当我们在excutor函数中调用resolve方法时,Promise的状态就变成fulfilled,即操作成功状态,当Promise状态为fullfilled状态时执行then方法里的操作。
  • 注意了,then方法里面有两个参数***onfulfilled***(Promise为fulfilled状态时执行) 和***onrejected***(Promise为rejected状态时执行)。

1. resolve的用法

  • 首先,实例化Promise
  • 然后,用Promise的实例调用then方法
const ps = new Promise((resolve, reject)=> {
            setTimeout(()=>{
                console.log('执行操作');
                resolve('这是数据');
            }, 1000);
        });

ps.then((data)=> {
      console.log(data);
      console.log('这是成功操作');
});
  • 控制台结果

UFZxkF.png

调用resolve方法后,Promise变为操作成功状态(fulfilled),执行then方法里面onfulfilled里的操作。
其实then里面的函数就是我们平时所说的回调函数,只不过在这里只是把它分离出来而已。

2. reject的用法

就是调用reject方法后,Promise状态变为rejected,即操作失败状态,此时执行then方法里面onrejected操作。

上面我们提到了then方法有两个参数,一种是Promise状态为fulfilled时执行  (onfullfilled),一种是Promise状态为rejected时执行(onrejected)
var ps = new Promise((resolve, reject)=> {
          let flag = false;
          if(flag){
            resolve('这是数据');
          }else{
            reject('这是数据');
          }
        });

        ps.then((data)=> {
            //状态为fulfilled时执行
            console.log(data);
            console.log('这是成功操作');
        },(reason)=> {
             //状态为rejected时执行
            console.log(reason);
            console.log('这是失败的操作');
        });

UFea1s.png

3. catch方法

除了then方法外,Promise原型上还有另外一个叫catch的方法。
其实跟then方法中的第二个参数一样,就是在Promise状态为rejected时执行,then方法捕捉到Promise的状态为rejected,就执行catch方法里面的操作

var ps = new Promise((resolve, reject)=> {
          let flag = false;
          if(flag){
            resolve('这是数据');
          }else{
            reject('这是数据');
          }
        });

        ps.then((data)=> {
            //状态为fulfilled时执行
            console.log(data);
            console.log('这是成功操作');
        }).catch((reason))=> {
             //状态为rejected时执行
            console.log(reason);
            console.log('这是失败的操作');
        });

执行结果和上面reject用法的例子一样


四、为什么会有promise,他的作用是什么?

  • Promise是异步编程的一种解决方案
  • promise主要是为了解决js中多个异步回调难以维护和控制的问题。

例如: (回调地狱问题)
回调函数的嵌套太多,使代码的可读性和可维护性都大大降低

嵌套太多的一个例子

取4个定时器,设置延迟时间都为1s,然后每隔1s依次在控制台输出1,2,3,4…

setTimeout( ()=> {
          console.log('1');
          setTimeout( ()=> {
              console.log('2');
              setTimeout( ()=> {
                  console.log('3');
                  setTimeout( ()=> {
                      console.log('4');
                  }, 1000);
              }, 1000);
          }, 1000);
      }, 1000);

如果我们使用Promise去实现这个效果,虽然可能代码不会减少,甚至更多,但是却大大增强了其可读性和可维护性

采用Promise来实现,避免了层层嵌套的回调函数

function getStr(param) {
    return new Promise( (resolve, reject)=> {
        setTimeout( ()=> {
            resolve(param);
        }, 1000);
    });
}

getStr('1').then( (data)=> {
    console.log(data);
    return getStr('2');
}).then( (data)=> {
    console.log(data);
    return getStr('3');
}).then( (data)=> {
    console.log(data);
    return getStr('4');
}).then( (data)=> {
    console.log(data);
})

将得到Promise实例的过程封装成一个函数getStr,并返回一个Promise实例,
再用实例去调用相应的then方法,
在每个then方法中通过return得到下一级的Promise实例,
然后再去调用then方法执行里面的操作,
再返回下一个Promise对象。

链式调用,虽然代码量增加了,但比起前面的层层嵌套,显然这种方式使得代码更易读更易维护


五、Promise的缺点

Promise 有一些缺点。
首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。


六、推荐

为了防止不可预知的bug,在生产项目中最好还是不要使用原生的或者自己编写的Promise(目前为止并不是所有浏览器都能很好的兼容ES6),而是使用已经较为成熟的有大量小伙伴使用的第三方Promise库,推荐一个—— Bluebird

浏览器兼容性
UFu9pQ.png


参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/69787.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!