promise分享总结

2019-03-18  本文已影响0人  我的天气很好啦
一、promise出现的原因

在JS的世界中,所有代码都是单线程执行。由于这个缺陷,导致JS的所有网络操作、浏览器事件都必须是异步执行。
通常异步执行可以采用回调函数的方法来异步执行
例如

function callback(){
  console.log('done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000);
console.log('after setTimeout');

观察上述代码,在chrome的控制台输出可以看到:

before setTimeout()
after setTimeout()
(等待一秒后)
Done

例如AJAX就是典型的异步操作,例如:

request.onreadystatechange = function() {
  if(request.readyState === 4){
    if(request.state === 200) {
      return success(request.responseText);
    }else{
      return fail(request.state);
    }
  }
}

把回调函数success(request.responseText)和fail(request.status)写到一个AJAX操作里很正常,但是不好看,而且不利于代码复用。
可以换个更好的写法,比如:

var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
      .ifFail(fail);

这种链式写法的好处在于,先统一执行AJAX的逻辑,不关心如何处理结果。然后根据结果的成功还是失败,在将来的某个时候调用success函数或者fail函数。

二、promise对象的的特点
三、promise的基本用法

promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JS引擎提供。

resolve(value)和resolve(promise)的区别

对比背景:我们会在异步操作成功时调用resolve函数,其作用是将promise对象的状态从pending变成resolved,并将异步操作的结果作为参数传递给then()方法里的第一个函数的形参。
那么传入的参数是值还是promise对象,有什么不同呢?
举例说明:

        传入的参数是值
        var time = new Date();
        var promise = new Promise(function(resolve, reject) {  
            setTimeout(function() { 
                console.log("2秒后,我运行了");
                resolve('异步操作成功了');     
            }, 2000) 
            
        }).then(function (value) {
            console.log(value,new Date() - time);
        })
        //执行的输出结果为:
        //2秒后,我运行了
        //异步操作成功了 2002
      传入的参数是promise对象
      var time = new Date();
        var promise = new Promise(function(resolve, reject) {  
            setTimeout(function() { 
                console.log("2秒后,我运行了");
                resolve('异步操作成功了');     //1
            }, 2000) 
            
        })

        var promise2 = new Promise(function (resolve,reject) {
            setTimeout(resolve,1000,promise);
        }).then(function (value) {
            console.log(value,new Date() - time);
        })

        //执行后输出的结果为:
        //2秒后,我运行了
        //异步操作成功了 2003

这里要讨论的是,为什么第二段代码中,promise2设置的执行时间是1秒,为什么还会2秒后打印~
简单说就是promise2中的resolve()函数传入了promise对象,此时promise对象的状态决定了promise的状态,同时会把返回值传给promise。

Promise/A+中规定
2.3.2.如果x是一个promise实例, 则以x的状态作为promise的状态
2.3.2.1.如果x的状态为pending, 那么promise的状态也为pending, 直到x的状态变化而变化。
2.3.2.2.如果x的状态为fulfilled, promise的状态也为fulfilled, 并且以x的不可变值作为promise的不可变值。
2.3.2.3.如果x的状态为rejected, promise的状态也为rejected, 并且以x的不可变原因作为promise的不可变原因。
2.3.4.如果x不是对象或函数,则将promise状态转换为fulfilled并且以x作为promise的不可变值

promise与错误状态处理 .catch()方法
var promise = new Promise(function(resolve, reject){
  setTimeout(function() {
    reject(''error);
  }, 2000)
}).then(null, function(error) {
    console.log('rejected', error)
  })
//rejected error

为了捕获异常信息,我们需要为每一个then()方法绑定一个.then(null, rejection)。由于promise对象的错误信息具有“冒泡”性质,错误会一直向后传递,直到被捕获为止。

var promise = new Promise(function(resolve, reject){
  setTimeout(function () {
    reject('error')
  }, 2000)
}).then(function {
    console.log('resolve', value)
}).catch(function (error) {
  console.log(error)
})

上面代码中,一共有两个promise对象,一个由promise产生,一个由then产生,它们之中任何一个抛出的错误,都会被最后一个catch捕获。
但是如果用.then(null, rejection)方法来处理错误信息,我们需要在每一个rejection()方法中返回上一次异常的信息状态,这样当调用的then()方法一多的时候,就会对代码的清晰和逻辑造成影响。
所以一般捕获异常用catch方法~

上一篇下一篇

猜你喜欢

热点阅读