阅读 108

Promise总结

  • 同步模式:后一个任务B等待前一个任务A结束后,再执行。任务的执行顺序和任务的排序顺序是一致的。
  • 异步模式:每一个任务有一个或多个回调函数,前一个任务A结束后,不是执行后一个任务B,而是执行任务A的回调函数。而后一个任务B是不等任务A结束就执行。任务的执行顺序,与任务的排序顺序不一致。

异步模式编程有四种方法:

  • 回调函数(最基本的方法,把B写成A的回调函数)、
  • 事件监听(为A绑定事件,当A发生某个事件,就执行B)、
  • 发布/订阅
  • Promise对象。

Promise是一个用于处理异步操作的对象,可以将回调函数写成链式调用的写法,让代码更优雅、流程更加清晰,让我们可以更合理、更规范地进行异步处理操作。它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

Promise的基本知识

1、三种状态

  • Pending:进行中,刚创建一个Promise实例时,表示初始状态;
  • resolved(fulfilled):resolve方法调用的时候,表示操作成功,已经完成;
  • Rejected:reject方法调用的时候,表示操作失败;

2、两个过程

三种状态只能从pendeng-->resolved(fulfilled),或者pending-->rejected,不能逆向转换,也不能在resolved(fulfilled)rejected之间转换;并且一旦状态改变,就不会再改变,会一直保持这个结果。

//创建promise的实例
const promise = new Promise((resolve, reject) => {
    //刚创建实例时的状态:pending

    if ('异步操作成功') {
        //调用resolve方法,状态从pending变为fulfilled
        resolve();
    } else {
        //调用reject方法,状态从pending变为rejected
        reject();
    }
});

3、then()

用于绑定处理操作后的处理程序,分别指定fulfilled状态和rejected状态的回调函数,即它的参数是两个函数,第一个用于处理操作成功后的业务,第二个用于处理操作失败后的业务。

//then()
promise.then((res)=> {
    //处理操作成功后的业务(即Promise对象的状态变为fullfilled时调用)
},(error)=> {
    //处理操作失败后的业务(即Promise对象的状态变为rejected时调用)
});

4、catch()

用于处理操作异常的程序,catch()只接受一个参数

//catch()
promise.catch((error)=> {
    //处理操作失败后的业务
});

一般来说,建议不要在then()里面定义rejected状态的回调函数,而是将then()用于处理操作成功,将catch()用于处理操作异常。因为这样做可以捕获then()执行中的错误,也更接近同步中try/catch的写法:

//try-catch
// bad
promise.then((res)=> {
    //处理操作成功后的业务
  }, (error)=> {
    //处理操作失败后的业务
  });

// good
promise.then((res)=> { 
    //处理操作成功后的业务
  })
  .catch((error)=> {
    //处理操作失败后的业务
  });

5、all()

接受一个数组作为参数,数组的元素是Promise实例对象。只有当参数中的实例对象的状态都为fulfilled时,Promise.all( )才会有返回。

//创建实例promise1
const promise1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('promise1操作成功');
        console.log('1')
    }, 3000);
});

//创建实例promise1
const promise2 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('promise2操作成功');
        console.log('2')
    }, 1000);
});


Promise.all([promise1, promise2]).then((result) => {
    console.log(result);
});

// 2
// 1
// ['promise2操作成功','promise1操作成功']

1s后,promise2进入fulfilled状态,间隔2s,也就是3s后,promise1也进入fulfilled状态。这时,由于两个实例都进入了fulfilled状态,所以Promise.all()才进入了then方法。

使用场景:执行某个操作需要依赖多个接口请求回的数据,且这些接口之间不存在互相依赖的关系。这时使用Promise.all(),等到所有接口都请求成功了,它才会进行操作。

6 race()

和all()的参数一样,参数中的promise实例,只要有一个状态发生变化(不管是成功fulfilled还是异常rejected),它就会有返回,其他实例中再发生变化,它也不管了。

//创建实例promise1
const promise1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve('promise1操作成功');
        console.log('1')
    }, 3000);
});

//创建实例promise1
const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('promise1操作失败');
        console.log('2')
    }, 1000);
});


Promise.race([promise1, promise2])
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log(error);
    });
// 2
// promise1操作失败
// 1

说明:1s后,promise2进入rejected状态,由于一个实例的状态发生了变化,所以Promise.race()就立刻执行了。

实例

需求:遇到的问题是,要用ajax进行多次请求。例如现在有三个请求,请求A、请求B、请求C。请求C要将请求B的请求回来的数据做为参数,请求B要将请求A的请求回来的数据做为参数。

//------请求A 开始---------
$.ajax({
    success: function (res1) {

        //------请求B 开始----
        $.ajax({
            success: function (res2) {

                //----请求C 开始---
                $.ajax({
                    success: function (res3) {
                    }
                });
                //---请求C 结束---

            }
        });
        //------请求B 结束-----

    }
});
//------请求A 结束---------

在请求A的success后,请求B发送请求,在请求B 的success后,请求C发送请求。请求C结束后,再向上到请求B结束,请求B结束后,再向上到请求A结束。

const promise = new Promise((resolve, reject) => {

    if (true) {
        //调用操作成功方法
        resolve('操作成功');
    } else {
        //调用操作异常方法
        reject('操作异常');
    }
});

//then处理操作成功,catch处理操作异常
promise.then(requestA)
    .then(requestB)
    .then(requestC)
    .catch(requestError);

function requestA() {
    console.log('请求A成功');
    return '下一个是请求B';
}

function requestB(res) {
    console.log('上一步的结果:' + res);
    console.log('请求B成功');
    return '下一个是请求C';
}

function requestC(res) {
    console.log('上一步的结果:' + res);
    console.log('请求C成功');
}

function requestError() {
    console.log('请求失败');
}

// 请求A成功
// 上一步的结果:下一个是请求B
// 请求B成功
// 上一步的结果:下一个是请求C
// 请求C成功

看出请求C依赖请求B的结果,请求B依赖请求A的结果,在请求A中是使用了return将需要的数据返回,传递给下一个then()中的请求B,实现了参数的传递。同理,请求B中也是用了return,将参数传递给了请求C。

作者:菠萝ZJP

原文链接:https://www.jianshu.com/p/240ffa200a32

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐