总结一下ES6的promise

基本用法

promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,其中resolve函数会将pending状态改为fulfilled,reject函数将pending改为rejected状态,状态一旦改变,将不可逆。这两个函数的函数的参数将会传给回调函数

const promise = new Promise(function(resolve, reject) {
        // ... some code

        if (/* 异步操作成功 */){
            resolve(value);
        } else {
            reject(error);
        }
    });
    promise.then((value)=>{ 
        console.log(value)
    },(error)=>{
        console.log(error)
    })

 

then方法

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数,第一个是状态由pending->fulfilled的回调,第二个是pending->resolved的回调。
then为什么可以进行链式调用呢?原因就是then方法返回的也是一个promise对象,所以后面可以继续使用then()方法。
此处有个地方需要注意,着重理解下面这句话:
Values returned from the onFulfilled or onRejected callback functions will be automatically wrapped in a resolved promise.
then()的两个参数函数中返回的值,会自动包装成一个已resolved的promise。(意思是在.then 或者 .catch 中 return一个值出去,都会被封装成resolve(值)的形式传给后面的.then或者.catch的回调,也可以直接return 一个新的Promise对象,不过这种方法不同的是可以控制这个即将要被return出去的Promise的状态为resolve()或者reject() )


代码1:

$http({
            method: 'GET',
            url: 'https://www.runoob.com/try/angularjs/data/sites.php1'
        }).then(function successCallback(data_1) {
            $scope.res = data_1;
            $scope.names = data_1.data.sites;
            return data_1;
        },function (err_1) {
            console.log("err_1",err_1);
            return err_1;
        }).then(function (data_2) {
            console.log("data_2", data_2)
        },function (err_2) {
            console.log("err_2---->",err_2);
        }).catch(function (reason) {
            console.log("err------->",reason);
        });

 

注:$http返回的是一个promise对象。

结果如下:
图片描述

网络请求404->失败的回调函数err_1方法->成功的回调函数(why),原因就是then中的回调函数,无论是成功回调还是失败回调,他们return的值都会被包装成promise的对象的resolved函数来处理,从而会传递给下一个then方法的成功回调函数里面去。
代码2:

Promise.resolve()
        .then(() => {
            return new Error('error!!!')
        })
        .then((res) => {
            console.log('then: ', res)
        })
        .catch((err) => {
            console.log('catch: ', err)
        })

 

结果是:
then: Error: error!!!
at Promise.resolve.then (...)
at ...

 

原因是:.then 或者 .catch 中 return 一个 error 对象并不会抛出错误,而是通过resolved来处理的,所以不会被后续的 .catch 捕获,需要改成其中一种:

1.return Promise.reject(new Error('error!!!'))
2.throw new Error('error!!!')

 

catch方法

Promise.prototype.catch方法是.then(null, rejection)的语法糖,用于指定发生错误时的回调函数。
1.then方法中没有第二个失败回调函数,当reject后,会进入catch方法;若then方法有第二个失败
回调,则reject后会进入此函数,而不会进入catch方法。

$http({
            method: 'GET',
            url: 'https://www.runoob.com/try/angularjs/data/sites.php'
        }).then(function successCallback(data_1) {
            $scope.res = data_1;
            $scope.names = data_1.data.sites;
            return data_1;
        },function (err_1) {
            console.log("err_1",err_1);
            return err_1;
        }).catch(function (reason) {
            console.log("err------->",reason);
        });

 

结果:
图片描述

当没then有第二个回调函数,则会进入catch方法。
小疑问:catch方法中return一个数值,在其后面的.then()的成功回调中会接收到么?答案是会的,把catch看做成没有成功回到的.then(),其return的数值也会被resolved出去。
注意:不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)

// bad
promise
  .then(function(data) {
    // success,标记1.要是在此处代码抛出了错误,此then函数的失败回调函数是捕捉不到的。
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

 

即:如果在“标记1”出代码抛出错误,后面的失败回调函数是捕捉不到的(只能捕捉上一个promise对象抛出的错误,自己所处在的then中是捕捉不到的),而只能被下一个then函数的失败回调(也就是catch)捕捉到。
例子:

Promise.resolve()
        .then(function success (res) {
            throw new Error('error')
        }, function fail1 (e) {
            console.error('fail1: ', e)
        })
        .catch(function fail2 (e) {
            console.error('fail2: ', e)
        })

 

结果:

fail2: Error: error
at success (...)
at ...

 

.then 可以接收两个参数,第一个是处理成功的函数,第二个是处理错误的函数。.catch 是 .then 第二个参数的简便写法,但是它们用法上有一点需要注意:.then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,而后续的 .catch 可以捕获之前的错误
以下代码也可以:

Promise.resolve()
        .then(function success1 (res) {
            throw new Error('error')
        }, function fail1 (e) {
            console.error('fail1: ', e)
        })
        .then(function success2 (res) {
        }, function fail2 (e) {
            console.error('fail2: ', e)
        })
posted @ 2020-01-09 15:41  寒江孤影,江湖路人  阅读(262)  评论(0编辑  收藏  举报