一、介绍:

通过打印可以看出Promise是一个构造函数,有all、reject、resolve、then、catch等方法。这样用Promise new出来的对象肯定就有then、catch等方法。 

二、用法:

created() {
    var p = new Promise(function (resolve, reject) {
      //做一些异步操作
      setTimeout(function () {
        console.log('Promise执行');
        resolve('这是Promise返回的数据');
      }, 2000);
    });
  }

虽然只new了一个对象,并没有调用它。但是打开页面,会在2秒后输出“Promise执行”。所以用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

 created() {
    this.testPromise()
  },
  methods: {
    testPromise() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('Promise执行');
          resolve('这是Promise返回的数据');
        }, 2000);
      });
    }
  }
test(){
   return new Promise((resolve, reject) => {
        api
          .then(data => {
            //你的逻辑
            resolve();
          })
          .catch(err => {
            //返回错误
            reject(err);
          });
      });
}

包装好的函数最后,会return出Promise对象,执行这个函数就得到了一个Promise对象,就可以使用then、catch等方法。 

三、resolve和reject:Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来讲,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。

1、resolve:作用是把resolve的状态置为resolved,在resolve中返回Promise的数据。相当于普通函数的return。如果不需要返回数据,则resolve();即可。

2、reject:作用就是把Promise的状态置为rejected,这样在then中就能捕捉到,然后执行“失败”情况的回调。

举例:

created() {
    this.testPromise().then(
      function (data) {
        console.log('resolved'+" "+data);
      },
      function (reason, data) {
        console.log('rejected'+" "+reason);
      }
    );
  },

 methods: {
    testPromise() {
      return new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          var num = Math.ceil(Math.random() * 10); //生成1-10的随机数
          if (num <= 5) {
            resolve(num);
          }
          else {
            reject('数字太大了');
          }
        }, 2000);
      });
    }
}

 成功的输出

失败的输出异常

四、then、catch、all、race的用法: 

1、then:then接收一个参数,是函数,效果和回调函数有些类似。如果用回调函数的话,假如callback也是一个异步操作,而且执行完后也需要有相应的回调函数,需要再定义一个callback2,然后callback传进去。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。从表面上看,Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。then的链式操作,所以使用Promise的正确场景是这样的:

 created() {
    this.testPromise()
  },
  methods: {
    testPromise() {
      this.runAsync1()
        .then(data => {
          console.log(data);
          return this.runAsync2();
        })
        .then(data => {
          console.log(data);
          return this.runAsync3();
        })
        .then(function (data) {
          console.log(data);
        });
    },
    runAsync1() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务1执行完成');
          resolve('这是Promise1返回的数据');
        }, 1000);
      });
      return p;
    },
    runAsync2() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务2执行完成');
          resolve('这是Promise2返回的数据');
        }, 1000);
      });
      return p;
    },
    runAsync3() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务3执行完成');
          resolve('这是Promise3返回的数据');
        }, 1000);
      });
      return p;
    }
  }

 在then方法中,也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了,比如把上面的代码修改成这样: 

 testPromise() {
      this.runAsync1()
        .then(data => {
          console.log(data);
          return this.runAsync2();
        })
        .then(data => {
          console.log(data);
          return '直接返回数据'; 
        })
        .then(function (data) {
          console.log(data);
        });
    }

  

2、catch:和then的第二个参数一样,用来指定reject的回调,效果和写在then的第二个参数里面一样。

 created() {
    this.testPromise().then(function (data) {
      console.log('resolved' + " " + data);
    })
      .catch(function (reason) {
        console.log('rejected' + " " + reason);
      });
  },
  methods: {
    testPromise() {
      return new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          var num = Math.ceil(Math.random() * 10); //生成1-10的随机数
          if (num <= 5) {
            resolve(num);
          }
          else {
            reject('数字太大了');
          }
        }, 2000);
      });
    }
}

不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了)捕获异常,与try/catch类似:

  this.testPromise().then(function (data) {
      console.log('resolved' + " " + data);
      //此处aaa没有定义,会抛出异常
      console.log(aaa);
    })
      .catch(function (reason) {
        console.log('rejected' + " " + reason);
      });

3、all: Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。如一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,再进行页面的初始化。

 created() {
    this.testPromise();
  },
  methods: {
    testPromise() {
      Promise
        .all([this.runAsync1(), this.runAsync2(), this.runAsync3()])
        .then(function (results) {
          console.log(results);
        });
    },
    runAsync1() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务1执行完成');
          resolve('这是Promise1返回的数据');
        }, 1000);
      });
      return p;
    },
    runAsync2() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务2执行完成');
          resolve('这是Promise2返回的数据');
        }, 2000);
      });
      return p;
    },
    runAsync3() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务3执行完成');
          resolve('这是Promise3返回的数据');
        }, 3000);
      });
      return p;
    }
  }

  

4、race的用法:all方法的效果实际上是「谁跑的慢,以谁为准执行回调」。race和all相对,「谁跑的快,以谁为准执行回调」。

created() {
    this.testPromise();
  },
  methods: {
    testPromise() {
      Promise
        .race([this.runAsync1(), this.runAsync2(), this.runAsync3()])
        .then(function (results) {
          console.log(results);
        });
    },
    runAsync1() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务1执行完成');
          resolve('这是Promise1返回的数据');
        }, 1000);
      });
      return p;
    },
    runAsync2() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务2执行完成');
          resolve('这是Promise2返回的数据');
        }, 2000);
      });
      return p;
    },
    runAsync3() {
      var p = new Promise(function (resolve, reject) {
        //做一些异步操作
        setTimeout(function () {
          console.log('异步任务3执行完成');
          resolve('这是Promise3返回的数据');
        }, 3000);
      });
      return p;
    }
  }

 

再如:

//请求某个图片资源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = 'xxxxxx';
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

 如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐