欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对Promise的认识

程序员文章站 2024-03-15 20:38:36
...

一、Promise是什么?

  • ECMAscript 6 原生提供了 Promise 对象

  • 采用console.log(Promise)看一下它的结构组成
    对Promise的认识

可以看出,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('这是成功操作');
});
  • 控制台结果

对Promise的认识

调用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('这是失败的操作');
        });

对Promise的认识

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

浏览器兼容性
对Promise的认识


参考

相关标签: js