浅谈ES6中的promise(Marksheng)

控制台输出  console.log(promise)

1.什么是Promise (结合上图得出结论)

Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。(ps:什么是原型:https://blog.csdn.net/qq_37430247/article/details/112193991

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

2.

二,Promise的使用

首先我们来看一下Promise的使用语法:

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

在实例化Promise时需要传入一个函数excutor作为参数,并且在Promise构造函数执行时同步执行。废话不多说,先看一个简单的实例:

 
  1. var p = new Promise(function(resolve,reject){

    扫描二维码关注公众号,回复: 12495909 查看本文章
  2.              var timer = setTimeout(function(){

  3.                  console.log('执行操作1');

  4.              },1000);

  5.          });

我们可以看到1s后在控制台输出相应的结果,这就说明在实例化过程中,作为参数的excutor函数也会执行。

从上面的实例中我们看到,excutor函数还有两个参数resolve和reject,其实这两个参数也是函数,在excutor执行时被调用,下面我们具体来谈谈resolve和reject的用法。


三,resolve和reject的具体用法

先来说说resolve的用法

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

  • pending: 初始状态,成功或失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

       当我们在excutor函数中调用resolve方法时,Promise的状态就变成fulfilled,即操作成功状态,还记得上面Promise.prototype上面的then和catch方法吗?当Promise状态为fullfilled状态时执行then方法里的操作,注意了,then方法里面有两个参数onfulfilled(Promise为fulfilled状态时执行) 和onrejected(Promise为rejected状态时执行),步骤如下:

1,实例化Promise(new Promise(function(resolve,reject)))

2,用Promise的实例调用then方法

具体来看下面的例子:

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

            var timer = setTimeout(function () {

                console.log('执行操作1');

                resolve('这是数据1');

            }, 1000);

        });

        p.then(function (data) {

            console.log(data);

            console.log('这是成功操作');

        });

简单的理解就是调用resolve方法Promise变为操作成功状态(fulfilled),执行then方法里面onfulfilled里的操作。其实then里面的函数就是我们平时所说的回调函数,只不过在这里只是把它分离出来而已。我们可以看到控制台上的输出结果如下所示:


reject的用法

        看了上面的实例,我相信应该也很容易理解reject方法了,就是调用reject方法后,Promise状态变为rejected,即操作失败状态,此时执行then方法里面onrejected操作,上面我们提到了then方法有两个参数,一种是Promise状态为fulfilled时执行(onfullfilled),一种是Promise状态为rejected时执行(onrejected),其实就是类似于jquery里的hover方法里面的两个参数一样,来看看下面的例子:

 
  1. var p = new Promise(function (resolve, reject) {
    
              var flag = false;
    
              if(flag){
    
                resolve('这是数据2');
    
              }else{
    
                reject('这是数据2');
    
              }
    
            });
    
            p.then(function(data){//状态为fulfilled时执行
    
                console.log(data);
    
                console.log('这是成功操作');
    
            },function(reason){ //状态为rejected时执行
    
                console.log(reason);
    
                console.log('这是失败的操作');
    
            });

 我们可以看到输出结果:


catch方法

       我们注意到除了then方法外,Promise原型上还有另外一个叫catch的方法,那么这个方法的作用是什么呢?其实跟then方法中的第二个参数一样,就是在Promise状态为rejected时执行,then方法捕捉到Promise的状态为rejected,就执行catch方法里面的操作,下面用catch方法改写上面reject用法里面的例子,如下所示:

 
  1. var p = new Promise(function (resolve, reject) {
    
                var flag = false;
    
                if(flag){
    
                  resolve('这是数据2');
    
                }else{
    
                  reject('这是数据2');
    
                }
    
              });
    
              p.then(function(data){
    
                  console.log(data);
    
                  console.log('这是成功操作');
    
              }).catch(function(reason){
    
                  console.log(reason);
    
                  console.log('这是失败的操作');
    
              });

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


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

promise主要是为了解决js中多个异步回调难以维护和控制的问题.

四,为何用Promise

首先我们来看这样一个例子,取4个定时器,设置延迟时间都为1s,然后每隔1s依次在控制台输出‘我’‘爱’‘米’‘饭’的字样。代码如下:

setTimeout(function () {

          console.log('我');

          setTimeout(function () {

              console.log('爱');

              setTimeout(function () {

                  console.log('米');

                  setTimeout(function () {

                      console.log('饭');

                  }, 1000);

              }, 1000);

          }, 1000);

      }, 1000);

发现什么问题没有?是不是有点感觉回调函数的嵌套有点多,如果有更多的回调函数呢?是不是使代码的可读性和可维护性都大大降低了呢(回调地狱?),这时如果我们使用Promise去实现这个效果,虽然可能代码不会减少,甚至更多,但是却大大增强了其可读性和可维护性。具体看下面例子:


function getStr1() {

    return new Promise(function (resolve, reject) {

        setTimeout(function () {

            resolve('我');

        }, 1000);

    });

}

function getStr2() {

    return new Promise(function (resolve, reject) {

        setTimeout(function () {

            resolve('爱');

        }, 1000);

    });

}

function getStr3() {

    return new Promise(function (resolve, reject) {

        setTimeout(function () {

            resolve('米');

        }, 1000);

    });

}

function getStr4() {

    return new Promise(function (resolve, reject) {

        setTimeout(function () {

            resolve('饭');

        }, 1000);

    });

}

getStr1().then(function (data) {

    console.log(data);

    return getStr2();

}).then(function (data) {

    console.log(data);

    return getStr3();

}).then(function (data) {

    console.log(data);

    return getStr4();

}).then(function (data) {

    console.log(data);

})

执行效果跟上面一样,在这个例子中,将得到Promise实例的过程封装成一个函数(getStr1,getStr2,getStr3,getStr4)并返回一个Promise实例,再用实例去调用相应的then方法,在每个then方法中通过return得到下一级的Promise实例,比如在第一个Promise实例(getStr1())then方法中,通过return返回下一个Promise对象(getStr2()),然后再去调用then方法执行里面的操作,再返回下一个Promise对象(这里是getStr3()),

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


小例子:


function checkFunc() {

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

// 一些比较耗时异步操作

if(操作完成标识) {

resolve();

}

});

p.then(function (data) {

layer.confirm('执行下一步操作?', {

btn: ['确定', '取消']

}, function () {

// 确保上面的操作都完成后,才执行下面的操作

// 其他操作...

});

});

}

猜你喜欢

转载自blog.csdn.net/qq_37430247/article/details/112193858