15

前言

ECMAScript 6 的正式版后,我们看到新增加了一个对象Promise,它是用来处理异步操作的,以前的异步操作书写并不是很美观,而且在回调函数中 returnthrow 并不会带到我们想要的状态。而Promise 很好的解决了这些问题。

了解 promise

promise 对象存在三种状态,进行中、结束、失败。当从进行中到结束状态或从进行中到失败状态时,会触发reslovereject函数。

Promise 对象用法

// 创建 promise
let promise = new Promise(function(reslove,reject){
    
    if(/ * 成功 */){  
       reslove(values) // 成功调用reslove函数
    }else{
       reject(values)  // 失败调用 reject函数
    }
})


// 调用

promise.then(function(val){
   // 调用reslove() 函数
},function(val){
   调用 reject() 函数
})

reslovereject 函数并不我们自己声明的,而是js底层为我们封装好的。当我们在 promise对象中成功时调用reslove函数,它会触发then方法中的第一个函数,当我们在 promise对象中成功时调用reject函数,它会触发then方法中的第二个函数,另外then中的第二个方法我们可以省略。我们可以使用 catch 来接受一些错误信息。

promise.then((val) =>{
    // 成功处理
}).catch((val) =>{
    // 错误处理
})

在创建的promise构造函数里或then的回调函数里遇到的错误信息都会被catch捕获到,我们来看一个例子

let promise = function(time){

    return new Promise(function(relove, reject){
      if(typeof time == 'number'){
        setTimeout(relove,time,"调用成功");
      }else{
          reject("调用失败")
      }
       
    })
}


promise(100).then((val) =>{
    console.log(val)  // 调用成功
})

promise("fda").then((val) =>{
    console.log(val)  // 调用失败
})

promise(100).then((val) =>{
    new throw("出错了")
    console.log(val)  // 不执行
}).catch((val) => {
    console.log(val)  //出错了 
})

现在我们应该对promise有一定的了解,使用promise还有一定的好处是,我们可以在then回调函数中去使用 return 语句和 throw 语句,上面我们已经使用了throw 语句。另外我们还可以在then的回调函数中去使用调用另一 promise 对象。这样比我们使用AJAX交互时嵌套访问清晰的多。

promiseOne.then(()=>{
    promiseTwo.then(() =>{

    })
}).catch(() =>{
    
})

另外,我们应该知道,then 方法和 catch 方法是绑定到了 promise对象的原型上边了。

Promise 对象的其他用法

1. Promise.all()

该方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

let promise = Promise.all([promiseOne,promiseTwo]);

这种情况下当 promiseOnepromiseTwo 都成功调用 promise 才会被成功调用,

2. Promise.race()

该方法同样是将多个Promise实例,包装成一个新的Promise实例。只不过在这种情况下,只要其中一个被成功调用,promise 就会被成功调用。

  1. Promise.resolve()

将对象转换为 Promise,这里有四中情况

(1)参数是一个Promise实例

let promise = new Promise(function(relove,reject){
    
})

// 返回promise
let promiseNew = Promise.resolve(promise) 

如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

(2)参数是一个thenable对象

thenable对象就是带有 then 方法的对象

let obj ={
    then(relove,reject){
        relove(111)
    }
}


let promiseNew = Promise.resolve(obj) 
promiseNew.then((val) =>{
    console.log(val)  // 111
})

这时Promise.resolve(obj) 会将obj转化为Promise对象,并立即执行then方法

(3)参数不是具有then方法的对象,或根本就不是对象

let promiseNew = Promise.resolve(1234) 

promiseNew.then((val) =>{
    console.log(val) // 1234
})

(4)不带有任何参数

// 返回一个 relove状态的Promise对象
let promiseNew = Promise.resolve()  

需要注意的是,立即resolve的Promise对象,实在事件循环结束时,而不是开始时,如:

setTimeout(function(){
    console.log(111)
})

Promise.resolve().then(() =>{
    console.log(222)
})

console.log(333)

// 333
// 222
// 111

setTimeout 是在下一个事件循环时执行,Promise.reslove 是在事件循环结束是调用, console 是立即调用

  1. Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

var p = Promise.reject('出错了');
// 等同于
var p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了

注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。

  1. done()

该方法是Promise 对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为Promise内部的错误不会冒泡到全局)。因此,我们可以提供一个done方法,总是处于回调链的尾端,保证抛出任何可能出现的错误。

promise.then()
       .catch()
       .then()
       .catch()
       .done() // 接收错误,并向全局抛出
  1. finally()

finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。

promise.then()
       .finally() // 不管then() 是否有错,finally都会执行

结束

promise 对象的使用并不是很难,这里我参考了阮一峰老师的书籍。

参考书籍:《ECMAScript 6 入门》


webxiaoma
747 声望27 粉丝

代码搬运工