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

初步认识 Promise

程序员文章站 2022-07-02 22:32:31
...

一、为什么会出现Promise

JS是单线程运行的,就是说一次只能完成一个任务,如果有多个任务必须排队依次完成,没有Promise的时候,我们完成一个卖商品的任务:
需要层层回调函数

        function sell(kehu,callback){
            console.log(`紫紫接受客户${kehu}的产品询问`);
            setTimeout(()=>{
                // 卖出东西的概率为 0.2
                if(Math.random() < 0.2){
                    //回调函数
                    callback(true)
                }else(
                    //回调函数
                    callback(false)
                )
            },1000)
        }

        //调用函数
        sell('小明',function(result){
             if(result){
               console.log(`商品种类较少,去别家看看`)
              }else{
                console.log(`颜色不太喜欢`)
                sell('芳芳',function(result){
                    if(result){
                        console.log(`商品种类较少,去别家看看`)
                    }else{
                        console.log(`颜色不太喜欢`);
                        sell('小王',function(result){
                            if(result){
                                console.log(`商品种类较少,去别家看看`)
                            }else{
                                console.log(`颜色不太喜欢`)
                                        }
                                     })
                                }
                           })
                        }
                    })
          })

这只是一个小任务,还没有多大问题,可是代码量不算少了;
所以promise出来了

二、什么是promise

利用 promise可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,promise对象提供统一的接口,似的控制异步操作更加容易。

但注意promise无法取消,一旦建立就会立即执行,无法中途取消。而且,如果不设置回调函数,promise内部抛出的错误不会反映到外部。当处于Pending状态时,无法得知进展到哪一个阶段。

promise有三个状态:

  1. Pending-promise的初始状态,等到任务完成或是被拒绝
  2. Resolved-执行完成并且成功的状态;
  3. Rejected-执行完成并且失败的状态。此三个状态不能相互逆转。

promise对象必须实现then方法,可以说then是promise的核心,而且then方法必须返回一个promise对象,同一个promise对象可以注册多个then方法,并且回调的执行顺序和他们注册的顺序一致。

then方法接收两个回调函数,他们分别是成功时的回调和失败时的回调。

三、Promise的用法

let p = new Promise((resolve, reject) => {
    //做一些异步操作
    setTimeout(() => {
        console.log('执行完成');
        resolve('我是成功!!');
    }, 2000);
});

then 链式操作的用法

Promise的使用比callback函数调用简单、灵活的多:

p.then((data) => {
    console.log(data);
})
.then((data) => {
    console.log(data);
})
.then((data) => {
    console.log(data);
});

reject的用法:

把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调

 let p = new Promise((resolve, reject) => {
        //做一些异步操作
      setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
      }, 2000);
    });
    p.then((data) => {
            console.log('resolved',data);
        },(err) => {
            console.log('rejected',err);
        }
    ); 

then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。

catch 的用法

我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调。用法是这样:

p.then((data) => {
    console.log('resolved',data);
}).catch((err) => {
    console.log('rejected',err);
}

果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中

p.then((data) => {
    console.log('resolved',data);
    console.log(somedata); //此处的somedata未定义
})
.catch((err) => {
    console.log('rejected',err);
});

在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。