前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS中Promise理解与应用

JS中Promise理解与应用

作者头像
Light413
发布2020-04-08 16:11:58
1.2K0
发布2020-04-08 16:11:58
举报

Promise 中文释义:许诺,允诺;希望。意指我答应你我会去做的,不管成功还是失败我肯定会做的。

1、基础介绍

PromiseES6一个新的特性,本身是个对象用于表示一个异步操作的最终完成 (或失败), 及其结果值。创建一个Promise对象:

代码语言:javascript
复制
var promise1 = new Promise(function(resolve, reject) {}  );

传入一个参数-函数function(resolve, reject) {},该函数本身两个参数也是函数。Promise执行构造函数时立即执行该函数function(resolve, reject) {},然后返回对象promise1。执行结果要么成功、要么失败:

  • 如果执行完成调用resolve ,promise1状态变为fulfilled 。
  • 如果失败调用reject,promise1状态变为rejected 。

Demo1——一个简单示例

代码语言:javascript
复制
//Demo1
var promise1 = new Promise(function(resolve, reject) {
    //这里通常执行一个异步任务比如网络数据请求等,成功返回调用resolve , 失败reject
    resolve('执行成功');
});

promise1.then(function(s){
    console.log('成功:' + s);
} , function(s){
    console.log("失败:"  + s);
})

//结果输出 成功:执行成功

所以可以理解为promise用不同的状态来标记事件不同的处理结果,当执行完成时状态为fulfilled , 失败时状态变为rejected。然后通过then方法绑定事件来处理不同的状态。

Promise有三种状态

pending: 初始状态,既不是成功,也不是失败状态。 fulfilled: 意味着操作成功完成。 rejected: 意味着操作失败。

状态变化只能有 pending-> fulfilled 或者 pending-> rejected 两种方式,一旦状态发生变化则保持固定不变。

2、方法介绍

then方法 ,原型 then(onFulfilled[, onRejected])

如上所述通过then方法对promise对象绑定处理事件 ,它最多需要有两个参数:Promise 的成功和失败情况的回调函数。 当成功时执行第一个参数onFulfilled的回调处理,失败执行第二个参数onRejected的回调处理,然后返回一个 新的Promise对象,然后可以继续添加then方法处理回调,以此可形成链式调用。

then方法是个很重要的方法,下面我们结合各种情况来示例说明

注意两个参数是可选的 如果调用 then 的 Promise 的状态(fulfillment 或 rejection)发生改变,但是 then 中并没有关于这种状态的回调函数,那么 then 将创建一个没有经过回调函数处理的新 Promise 对象,这个新 Promise 只是简单地接受调用这个 then 的原 Promise 的终态作为它的终态。

Demo2——then方法没有回调处理参数(无任何参数)

代码语言:javascript
复制
//demo2---then没有回调处理参数
var promise1 = new Promise(function(resolve, reject) {
    //这里通常一个异步任务比如网络数据请求等,成功返回调用resolve , 失败reject
    resolve('执行成功');
});

var promise2 = promise1.then()
promise2.then(function(v){
    console.log("v: " + JSON.stringify(v));
})

//或直接这样
/*promise1.then().then(function(v){
    console.log("v: " + JSON.stringify(v));
})*/

//输出 v: "执行成功"

新生成的对象promise2 状态直接是完成状态,接收上一级传递的参数,然后执行then中成功回调处理。

如果执行的reject('失败'),则会抛出一个错误异常,需要catch方法来捕获。

关于then返回值

当一个 Promise 完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回。如果 then 中的回调函数:

  • 1、返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 2、没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined。
  • 3、抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 4、返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 5、返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 6、返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。

Demo3——then方法中直接返回一个值

代码语言:javascript
复制
    //demo3---then直接返回一个值
    var promise1 = new Promise(function(resolve, reject) {
        //这里通常一个异步任务比如网络数据请求等,成功返回调用resolve , 失败reject
        resolve('执行成功');
    });
    
    var promise2 = promise1.then(
        function(value){
            return value;
        }
    )
    
    promise2.then(function(v){
        console.log("--v: " + JSON.stringify(v));
    })
    //输出--v: "执行成功"
then 回调总会返回一个promise对象,这个对象可以是隐式自动生成的,也可以是我们显示创建的。然后根据不同的状态在执行相应的回调处理。

catch方法 ,原型 catch(onRejected)

用于处理promise失败时错误捕获

Demo4——catch方法

代码语言:javascript
复制
    //demo4---catch方法
    var promise1 = new Promise(function(resolve, reject) {
        //这里通常一个异步任务比如网络数据请求等,成功返回调用resolve , 失败reject
        reject('执行失败');
    });
    
    var promise2 = promise1.then(function(value){
        console.log("执行成功" + value);//这里不会走到这里
    }/*,function(value){//如果放开这里,下面的catch 不会执行
        console.log('失败:' + value);
    }*/
        
    ).catch(function(err){
        console.log('err:' + err);
        return 'err promise'
    })
    
    console.log(promise2);

执行结果

image.png

如果then中有reject处理失败的回调,则不会执行catch。其实它的行为与调用Promise.prototype.then(undefined, onRejected) 相同。 (事实上, calling obj.catch(onRejected) 内部calls obj.then(undefined, onRejected)).

所以可以理解为 catch()等价于 then(undefined, onRejected)) , 但是使用catch来处理错误更合适。因为它也可以处理then成功回调处理中抛出的错误。

可以看出catch中本身返回一个promise对象且状态已完成。如果 catch中抛出一个错误或返回一个本身失败的 Promise , 通过 catch() 返回的Promise 被rejected;否则,它将显示为成功(resolved)。

Promise.reject(reason)

生成一个状态已失败的promise对象

Promise.resolve(value)

生成一个状态已完成的promise对象

all(iterable) 方法

Promise.all(iterable)

参数iterable :一个包含至少一个promise对象的数组。

类似于与操作,必须全部执行完成才触发接下来的操作。

方法返回一个新的 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。

如果我们有多个异步任务处理,最后要监听全部执行完成,此时all方法就很合适。

race()

Promise.race(iterable) 参数iterable :一个包含至少一个promise对象的数组。

此类似于或操作,只要有一个完成或失败就算结束。任意一个子promise执行成功或失败后就会生成一个新的promise,状态就是第一个promise的状态。

Demo5—— race方法

代码语言:javascript
复制
    //race方法
    var promise1 = new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('promise1 完成');
        } , 3000);
    })
    
    var promise2 = new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('promise2 完成');
        } , 1500);
    })
    
    var promise3 = new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve('promise3 完成');
        } , 2000);
    })
    
    Promise.race([promise1,promise2,promise3]).then(function(value){
        console.log("value: " + JSON.stringify(value));
    })


//输出 value: "promise2 完成"

promise2最先执行,所以其执行完成后就结束流程。

常用的方法基本以上几个,剩下的就是结合实际场景应用了。
3、Promise常见应用

Demo6—— promise添加多个方法

代码语言:javascript
复制
    var promise1 = new Promise(function(resolve,reject){
        resolve('执行完成');
    })
    
    promise1.then(function(value){
        console.log('1----' + value);
    })
    
    promise1.then(function(value){
        console.log('2----' + value);
    })
    
    promise1.then(function(value){
        console.log('3----' + value);
    })

输出:

image.png

对同一个promise对象添加多个处理方法,就是相当于同时监听一个事件。

Demo7 ——监听多个异步任务全部完成

代码语言:javascript
复制
    var promise1 = new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('promise1 完成');
            resolve('promise1 完成');
        } , 3000);
    })
    
    var promise2 = new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('promise2 完成');
            resolve('promise2 完成');
        } , 1500);
    })
    
    var promise3 = new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('promise3 完成');
            resolve('promise3 完成');
        } , 2000);
    })
    
    Promise.all([promise1,promise2,promise3]).then(function(value){
        console.log("value: " + JSON.stringify(value));
    })

输出结果:

image.png

all方法返回新的promise对象,回调处理函数参数和实际执行完成顺序无关,只和添加的顺序有关。

Demo8 ——实现链式操作 特别是一个异步任务请求数据要用于下一个任务操作的这种必须的先后次序总,尤为重要。

修改demo7要顺序执行:即依次输出promise1完成-promise2完成-promise3完成。

代码语言:javascript
复制
    var promise1 = new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('promise1 完成');
            resolve('promise1 完成');
        } , 3000);
    }).then(function(value){
        return new Promise(function(resolve,reject){
            setTimeout(function(){
                console.log('promise2 完成');
                resolve('promise2 完成');
            } , 1500);
        });
        
        return p
    }).then(function(value){
        return new Promise(function(resolve,reject){
            setTimeout(function(){
                console.log('promise3 完成');
                resolve('promise3 完成');
            } , 2000);
        });
        
        return p
    })

此时promise1对象就是最后一个then方法返回的对象,状态为接受状态,并且该接受状态的回调函数的参数值为 promise3 完成

执行结果:

image.png

4、总结
  • promise一旦开始不能终止。
  • 状态一旦改变就固定了,不会在被修改。
  • 在异步操作中抛出错误异常无法被捕获。

Promise主要用于异步处理,根据不同的状态执行相应的回调处理,有点类似其他系统的状态机的概念

ok , 关于Promise的介绍到此结束,理解了这些在实际应用中为我们多任务的异步处理又多一种选择。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、基础介绍
  • 2、方法介绍
  • 关于then返回值
    • then 回调总会返回一个promise对象,这个对象可以是隐式自动生成的,也可以是我们显示创建的。然后根据不同的状态在执行相应的回调处理。
      • 常用的方法基本以上几个,剩下的就是结合实际场景应用了。
    • 3、Promise常见应用
      • 4、总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档