Promise 有什么用+学习入门

2018-03-13  本文已影响2人  一个冬季

简介

最开始我是想了解bluebird,后来发现原来要了解bluebird,就先需要了解Promise,所以本节也是了解Promise的基本用法

学习这个有什么作用

1、可以减少很多callback回调的方法,减少层层的嵌套,让代码看起来更加的舒服。
2、针对代码里面存在异步方法时,可以等到异步方法执行完毕了再继续执行后面代码。

基本用法

Promise对象是一个构造函数,当我们要使用Promise,需要new一下

var promise = new Promise(function(resolve, reject) {
     //这里写你的主要代码
});

Promise构造函数接受一个函数作为参数,这个函数里面携带了二个方法
resolve与reject,当我们执行操作成功的时候,我们去调用resolve方法,失败的时候我们调用reject方法。为什么要这样规定呢?因为Promise存在三种状态,分别是
pending(进行中) ,fulfilled(已成功),rejected(已失败)
当我们调用promise时候,它就已经是处于进行中了,状态只能从pending-->fulfilled或者是pending-->rejected这二种情况

function testFunction() {
  return new Promise(function(resolve,reject){
     console.log('你好世界');
  });
}
var promise = testFunction();//立即执行
你好世界.png

可以看出,只要testFunction()方法一但调用,就会立即的执行。

更进一步then()用法,链式的使用

我们写代码的时候,代码逻辑程序基本上是从上到下,就像河流一样,从高处往低处流淌。

      function methond1(){
            var p = new Promise(function(resolve, reject){
                resolve("我是第一个方法");
            });
            return p;
        }
        function methond2(){
            var p = new Promise(function(resolve, reject){
                resolve("我是第二个方法");
            });
            return p;
        }
        function methond3(){
            var p = new Promise(function(resolve, reject){
                resolve("我是第三个方法");
            });
            return p;
        }
        function methond4(){
            var p = new Promise(function(resolve, reject){
                resolve("我是第四个方法");
            });
            return p;
        }
        methond1()
        .then(function(data){
             console.log(data);
            return methond2();
        })
         .then(function(data){
             console.log(data);
            return "我不调用第三个方法了";
        }).then(function(data){
             console.log(data);
             return methond4();
        }).then(function(data){
             console.log(data);
        }).then(function(data){
            console.log("德玛西亚");
        }).then(function(data){
            console.log("艾欧里亚");
        });
链式调用.png
从上面的代码里面可以说明几点:
1、使用return 可以调用方法,也可以把参数传递到下面
2、当我把参数放到resolve里面,可以在function(data)里面直接获取到
3、通过then可以直接链式逻辑写代码
4、data是上一个逻辑里面的数据
我们也可以看看其他博主大神写的
下面我直接复制吕大豹代码,我稍做了修改
function getNumber() {
            var p = new Promise(function (resolve, reject) {
                var num = Math.ceil(Math.random() * 10); //生成1-10的随机数
                if (num <= 8) {
                    resolve(num);
                } else {
                    reject('数字太大了');
                }
            });
            return p;
        }
          getNumber().then(function(data){
                    console.log('resolved');
                    console.log(data);
               },
                function(reason){
                    console.log('rejected');
                    console.log(reason);
                }
        );
数字正确调用.png 数字不正确调用.png

上面的代码可以知道then里面可以写2个方法,第一个方法是成功时候调用,第二个个是失败的时候调用。
如果我直接.then(),不像上面的代码会怎样呢?

 function methond1() {
        var p = new Promise(function (resolve, reject) {
             resolve("我是第一个方法");
         });
            return p;
        }
        function methond2() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第二个方法");
            });
            return p;
        }
        function methond3() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第三个方法");
            });
            return p;
        }
        function methond4() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第四个方法");
            });
            return p;
        }
         methond1()
         .then(function(data){
             console.log(data);
             return methond2();
         }).then(function(){ //这里我没有data了
             return "我不调用第三个方法了";
         }).then(function(data){
             console.log(data);
             return methond4();
         }).then(function(data){
             console.log(data);
         }).then(function(data){
             console.log("德玛西亚");
         }).then(function(data){
             console.log("艾欧里亚");
         }).catch(function(reason){
             console.log(reason);
         });
直接then().png

可以看到方法继续执行,没有受到任何的干扰。

又如果我注释掉return会怎样?

 methond1()
        .then(function(data){
              console.log(data);
              return methond2();
         }).then(function(data){
              console.log(data);
         //return "我不调用第三个方法了";   这里我注释了
         }).then(function(data){
              console.log(data);
              return methond4();
         }).then(function(data){
              console.log(data);
         }).then(function(data){
              console.log("德玛西亚");
         }).then(function(data){
              console.log("艾欧里亚");
         }).catch(function(reason){
              console.log(reason);
         });
去掉了return.png

可以看到去掉return后,继续执行代码。

catch捕获异常

当我们的程序从上到下一直执行的时候,执行到一半出现异常了,就可以使用catch来捕获

 function runAsync1() {
            var p = new Promise(function (resolve, reject) {
                //做一些异步操作
                setTimeout(function () {
                    console.log('异步任务1执行完成');
                    resolve('随便什么数据1');
                }, 1000);
            });
            return p;
        }
        function runAsync2() {
            var p = new Promise(function (resolve, reject) {
                //做一些异步操作
                setTimeout(function () {
                    console.log('异步任务2执行完成');
                    resolve('随便什么数据2');
                }, 2000);
            });
            return p;
        }
        function runAsync3() {
            var p = new Promise(function (resolve, reject) {
                //做一些异步操作
                setTimeout(function () {
                    console.log('异步任务3执行完成');
                    resolve('随便什么数据3');
                }, 2000);
            });
            return p;
        }
        function methond1() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第一个方法");
            });
            return p;
        }
        function methond2() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第二个方法");
            });
            return p;
        }
        function methond3() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第三个方法");
            });
            return p;
        }
        function methond4() {
            var p = new Promise(function (resolve, reject) {
                resolve("我是第四个方法");
            });
            return p;
        }
         methond1()
              .then(function(data){
               console.log(data);
               return methond2();
         }).then(function(data){
               console.log(data);
               return "我不调用第三个方法了";
         }).then(function(data){
              console.log(data);
              console.log(bbbbbbbbbbb); //这里的bbbbbbbbbbb我没有定义它,捕获异常
              return methond4();
          }).then(function(data){
              console.log(aaaaaaa);//这里我也没有定义它
         }).then(function(data){
              console.log("德玛西亚");
         }).then(function(data){
              console.log("艾欧里亚");
         }).catch(function(reason){//这里是捕获异常
              console.log(reason);
         });
异常捕获.png

从上面的图片结果来看我们可以总结下:
1、当出现程序异常,会直接进入catch。
2、当出现异常,后面的代码不会继续执行。

链接中途捕获异常

 methond1()
         .then(function(data){
             console.log(data);
             return methond2();
         })
         .then(function(data){
             console.log(data);
             return Promise.reject(new Error("啦啦啦啦"));
         }).then(function(data){
            console.log(data);
            return methond4();
         }).then(function(data){
            console.log(data);
         }).then(function(data){
            console.log("德玛西亚");
         }).then(function(data){
            console.log("艾欧里亚");
         }).catch(function(reason){
             console.log(reason);
         });
链接中途捕获异常.png

从上面的图片结果来看我们可以总结下:
1、当链接中途发生异常后续不再执行

异步全部执行完毕了再回调-->all方法

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,比如这

var promise = Promise.all([pro1,pro2, pro3]);

从上面代码我们知道,他接受一数组,pro1,pro2,pro3 都是要Promise 实例,promise 的状态由pro1,pro2, pro3共同决定,只要有1个失败了,那么就是失败的

    function methond1(){
            var p = new Promise(function (resolve, reject) {
                setTimeout(console.log("methond1"),2000);
                resolve("100");
            });
            return p;
        }
    function methond2(){
            var p = new Promise(function (resolve, reject) {
                setTimeout(console.log("methond2"),2000);
                resolve("200");
            });
            return p;
        }
    function methond3(){
            var p = new Promise(function (resolve, reject) {
                setTimeout(console.log("methond3"),2000);
                resolve("300");
            });
            return p;
        }
   Promise.all([methond1(), methond2(), methond3()])
                .then(function(results){
                    console.log(results);
                });
all方法的使用.png

从最后的结论中,我们可以总结以下
1、最后的100,200,300的数据显示是一个集合,并且当所有的promise执行完后才显示的。

then()里面遇见return 后续then()继续执行
       function taskA() {
            console.log("Task A");
        }
        function taskB() {
            console.log("Task B");
            return;  //这里打了return了
            console.log("Task C");
        }
        function onRejected(error) {
            console.log("Catch Error: A or B", error);
        }
        function finalTask() {
            console.log("Final Task");
        }
 var promise = Promise.resolve();
        promise
                .then(taskA)
                .then(taskB)
                .then(finalTask)
                .catch(onRejected);
后续return继续执行.png
手动结束/终止链接调用
      function taskA() {
            console.log("Task A");
        }
        function taskB() {
            console.log("Task B");
            return Promise.reject(new Error("手动抛出异常"));
        }
        function onRejected(error) {
            console.log(error)
        }
        function finalTask() {
            console.log("Final Task");
        }
        var promise = Promise.resolve();
        promise
                .then(taskA)
                .then(taskB)
                .then(finalTask)
                .catch(onRejected);
手动抛异常.png

我又参考了其他文献新增总结如下

  1. 使用promise.then(onFulfilled, onRejected) 的话
    • onFulfilled 中发生异常的话,在 onRejected 中是捕获不到这个异常的。
  2. promise.then(onFulfilled).catch(onRejected) 的情况下
    • then 中产生的异常能在 .catch 中捕获
  3. .then.catch在本质上是没有区别的
    • 需要分场合使用。

参考与摘要:
https://www.cnblogs.com/lvdabao/p/es6-promise-1.html 说的很好这一篇。
https://wohugb.gitbooks.io/ecmascript-6/content/docs/promise.html 入门

上一篇下一篇

猜你喜欢

热点阅读