天天看点

ES6 Promise详解什么是Promise?Promise基本用法Promise.all()Promise.race()Promise.resolve()Promise.reject()

什么是Promise?

首先Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个构造函数,他本身有all,race,reject,resolve方法,原型上有then,catch等方法,可以再控制台打印看下

ES6 Promise详解什么是Promise?Promise基本用法Promise.all()Promise.race()Promise.resolve()Promise.reject()

 Promise对象有两个特点:

  1. 对象状态不受其他影响,Promise对象代表一个异步操作,它有三种状态,pending(进行中),fulfilled(已成功),rejected(已失败),只有异步操作可以决定当前是哪一种状态,任何其他操作都无法改变其状态。
  2. 一旦状态改变,就不能再变,任何时候都可以得到这个结果,Promise状态的改变,只有两种可能:一种是从pending变为fulfilled,一种就是从pending变为rejected。

Promise基本用法

var p=new Promise(function(reslove,reject){
      if(/*操作成功*/){
         reslove(xx)
      }else{
         reject(xx)
      }
}) 
           

promise接受两个参数,一个是reslove,一个reject。

reslove就是把状态从pending转为fulfilled,再异步操作成功后调用,而reject就是把状态从pending转为rejected,和resolve相反,两种都可把操作结果作为参数,传递出去。

这时候,我们就可以用之前看到的原型的then方法了,then方法就是用来接受成功和失败状态的回调函数的,then方法接受两个回调函数,一个是成功的回调,一个是失败的回调(可选)。

var p=new Promise(function(reslove,reject){
      reslove("哈哈,成功了")
})
p.then(function(data){
     console.log(data)
},function(error){
     console.log(error)
})   
           

由于then方法返回了一个新的Promise实例,因此可以链式调用,这也就解决了回调地狱。

function runAsync1(){
            var p=new Promise(function(reslove,reject){
                setTimeout(function(){
                    reslove('xx1');
                },2000)
            })  
            return p;
        }
        function runAsync2(){
            var p=new Promise(function(reslove,reject){
                setTimeout(function(){
                    reslove('xx2');
                },5000)
            })  
            return p;
        }
        function runAsync3(){
            var p=new Promise(function(reslove,reject){
                setTimeout(function(){
                    reslove('xx3');
                },2000)
            })  
            return p;
        }  
        runAsync1().then(function(data){
            console.log(data);
            return runAsync2()
        }).then(function(data){
            console.log(data);
            return runAsync3()
        }).then(function(data){
            console.log(data);
        })
        //xx1
        //xx2
        //xx3
           

需要注意的是,Promise实例化后会立即执行的。

var p = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});
p.then(function() {
  console.log('resolved.');
});
console.log('Hi!');  
//Promise
//Hi!
//resolved.
           

还需要注意的是,resolve之后,不会阻塞后面的代码运行的。

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
//2
//1
           

 接下来就讲一下,catch()是用来干嘛的,它用来指定发生错误的回调函数。

var promise = new Promise(function(resolve, reject) {

resolve(x+1);

});

promise.then(function(data){

console.log(data)

}).catch(function(error) {

console.log(error);

});
           

如果状态已经发生改变,再不会抛出错误,如下直接走then方法。

var promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
           

另外,catch只捕获函数体内的

var promise = new Promise(function(resolve, reject) {
  resolve('ok');
  setTimeout(function(){
    throw new Error("错误")
  },100)
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
           

Promise.all()

promise.all就是多个Promise实例并行执行,参数接受一个数组,需等到全部状态都变为fulfilled才输出。

function runAsync1() {
    var p = new Promise(function (reslove, reject) {
        setTimeout(function () {
            reslove('xx1');
        }, 2000)
    })
    return p;
}
function runAsync2() {
    var p = new Promise(function (reslove, reject) {
        setTimeout(function () {
            reslove('xx2');
        }, 500)
    })
    return p;
}
function runAsync3() {
    var p = new Promise(function (reslove, reject) {
        setTimeout(function () {
            reslove('xx3');
        }, 400)
    })
    return p;
}
Promise.all([runAsync1(),runAsync2(),runAsync3()]).then(function(data){
    console.log(data);//['xx1','xx2','xx3']
}) 
           

需要注意的是,当一个被rejected,就会立即返回,then的结果是第一个被rejected的结果。

Promise.race()

promise.race同样是多个Promise实例并行执行,参数同样接受一个数组,和all不同的是,谁的状态先变为fulfilled,谁先返回并把结果传递给then。

Promise.race([runAsync1(),runAsync2(),runAsync3()]).then(function(data){
      console.log(data);//xx1
})
           

Promise.resolve()

就是把现有对象转为promise对象,他有四种情况:

第一种:参数是promise实例,那么将不做任何改变,将其返回。

第二种,参数是thenable对象

thenable对象指的是带属性then的对象,那么Promise.resolve,会将其转为promise对象,并把状态变为resolved,执行它所定义的then方法。

var thenable = {
  then: function(resolve, reject) {
    resolve('执行我的吧');
  }
};

var p1 = Promise.resolve(thenable);
p.then(function(value) {
  console.log(value);  //'执行我的吧'
});
           

第三种,参数不是thenable对象或根本不是对象

var p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello
           

第四种,就是无参数,其结果是直接返回一个

resolved

状态的 Promise 对象。

需要特别注意的是,promise.resolve的对象,是在本轮“事件循环”结束时,而不是下一轮事件开始时,之后我会专门写一篇关于eventloop的文章,不懂的朋友到时可以看下。

setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');

// one
// two
// three
           

Promise.reject()

该方法也会返回一个新的 Promise 实例,该实例的状态为rejected,需要注意的是,该方法会原封不动地作为reject的理由,变成后续方法的参数。这一点和Promise.resolve方法不一致

var thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true
           
es6