Promise详解

Promise是什么

抽象表达式:Promise是JS异步编程的新的解决方案(旧的方案是纯会调函数的形式来实现,容易形成毁掉地狱)

具体表达:

​ 1、从语法上来说,Promise是一个构造函数

​ 2、从功能上来说,Promise对象(函数对象,注意区分函数对象和实例对象的区别)用来封装一个异步操作并可以获得其结果。

Promise的状态改变

Promise有三种状态(pendding,resolved,rejected)

变化:1、pending变为resolved

​ 1、pending变为rejected

注意:状态改变只有这两种,且一个Promise对象只能改变一次状态,无论是成功还是失败,都会有一个结果数据,成功的数据我们一般称为value,失败的数据一般称为reason。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJUsv9rU-1585067502486)(C:\Users\joey\AppData\Roaming\Typora\typora-user-images\image-20200323204620737.png)]

过程解读:首先我们创建一个新的promise实例对象,初始状态为pendding,并且传入参数resolve和reject两个回调函数,然后执行异步任务:

new Promise(resolve,reject)

执行异步任务后,结果可能是失败可能是成功,如果成功就调用resolve回调,然后promise的状态变为resolved状态,然后调用then方法(参数是定义失败和成功的两个回调函数),返回一个新的promise对象(状态为resolved);如果结果是失败的,那么执行reject回调,promise状态改变为rejected,调用then或者catch方法(catch只能指定失败的回调,then返回一个新的promise对象(状态为rejected))

注意:除了resolve和reject,我们还可以通过throw来改变promise的状态,throw任意值都会使promise的状态变为rejected,如下所示:

new Promise((resolve,reject)=>{
            throw 9
        }).then(
            value=>{},
            reason=>{
                console.log(reason);  //9
            }
        )

如何使用Promise

创建一个Promise实例对象,传入一个回调函数,这个回调我们称为执行器函数(excutor,注意执行器函数是同步执行的,then方法是异步执行的),执行异步任务的,这个函数有两个参数,resolve和reject,这也是两个回调函数,注意promise实例化的时候会立即执行:

const p = new Promise((resolve,reject)=>{
    
})

如果成功,调用resolve,如果失败,调用reject。

然后我们可以用then方法来定义成功或者失败的回调函数(onResolved),成功的函数用来接收成功的value,失败的函数(onRejected)用来接收失败的reason。

p.then(
	value => {},
    reason => {}
)

下面就举一个Promise的基本使用的例子:

 const p = new Promise((resolve, reject) => {
            const time = Date.now();
            if (time % 2 == 0) {
                resolve("success");
            } else {
                reject("failed");
            }
        });
        p.then(
            value => {
                console.log("成功了", value);
            },
            reason => {
                console.log("失败了", reason);
            });

代码解读:我们生成一个新的promise对象,并且再其内部判断当前时间是不是偶数,如果是则返回成功的promise,promiseValue为"success",如果是奇数,则返回失败的promise,promiseValue为"failed"。这个就是一个简单的promise使用;注:这里只是为了演示Promise的基本使用,我们日常开发中,promise都是用来封装异步操作的。

为什么要用Promise(相比较之前的纯回调函数解决异步编程)

1、指定回调函数的方式更加灵活。

​ 解析:我们之前采用的纯回调的形式必须在异步任务执行之前就指定好回调函数(完成后指定回调函数的话是得不到数据的)。

​ 而Promise的方式可以在异步任务完成后再指定回调,因此是更加灵活的。

**2、**promise:启动异步任务=>返回promie对象一>给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)。

**3、支持链式调用,**可以解决回调地狱(金字塔厄运)问题。

什么是回调地狱:回调函数嵌套调用,多个异步操作是连续串联执行的,内部回调函数(异步任务)是以他外部回调函数的结果为条件的,这样如果是多个异步任务嵌套调用,会形成回调地狱(回调函数的嵌套),使得代码不便于阅读 ,不便于异常处理。

step1(function(result1) { 
  step2(function(result2) {
    step3(function(result3) { 
      // 以此类推
    }); 
  });
});

promise解决:

使用promise异步编程,由于promise支持链式调用,使得我们不用再去嵌套回调函数。因为我们会用promise封装一个异步操作,返回的是一个promise对象,一旦得到一个promise,说明启动了一个异步任务(一个promise对应一个异步任务),成功后开启第二个异步任务,这样类似的一次调用,代码是从上往下编码,方便阅读。

doSomething()
    .then(function (result) {
        return doSomethingElse(result)
    })
    .then(function (newResult) {
        return doThirdThing(newResult)
    })
    .then(function (fina1Result) {
        console.log('Got the final result: ,+ finalResult')
    })
    .catch(failureCallback)

而且我们处理异常更加方便,因为他们中任何一个出了异常,都会传到最下面(依次逐级传递,而不是一次性直接传到最下面,被catch捕获到,我们称为异常传透)。

Promise的语法(API)

API:一般指的是前后端交互的接口,但是在这里我们指的是语法,就是promise的用法。

1、excutor 执行器,(同步)回调函数,参数是两个回调函数resolve和reject,分别为成功和失败调用的回调。

2、resolve 内部定义成功时我们调用的函数 value => { }

3、reject 内部定义失败时我们调用的函数 reason=> { }

**注意:**excutor会在Promise内部立即同步执行回调,异步操作在执行器中进行。

4、Promise.prototype.then( ) 方法,所有的Promise实例对象都可以调用then方法,不管是成功的Promise还是失败的,所以这个方法是定义在Promise的原型prototype上面的。该方法返回一个新的Promise实例对象,这也是Promise能够实现链式调用的根本和前提。

		 p.then(
            value => {   //语法上讲,我们可以自定义value或者reason的名字
                //但我们约定俗成就用这两个参数名称
                console.log("成功了", value);
            },
            reason => {
                console.log("失败了", reason);
            }
         );

5、Promise.resolve(value) 该方法返回一个新的Promise实例对象,该对象的PromiseValue 就是传入的参数value。

6、Promise.prototype.catch方法: (onRejected) => { }

onRejected函数:失败的回调函数(reason) => { }

说明: then()的语法糖。相当于: then(undefined, onRejected)

7、Promise.reject方法: (reason) => 0)

reason:失败的原因

说明:返回一个失败的promise对象。

8、Promise.all方法 :(promises)=> { }

方法说明:该方法的参数回调中的参数promises指的是多个promise对象,也就是一个包含n个promise的数组,返回一个新的Promise,只有所有的promise都成功才算成功,其中一个失败则立即返回一个失败的promise

9、Promise.race方法 :(promises)=> { }

方法说明:该方法的参数回调中的参数promises指的是多个promise对象,也就是一个包含n个promise的数组,返回一个新的Promise,这个Promise的结果状态就是数组中传入的Promises中第一个完成的promise的结果状态。

代码理解:

		const p1 = new Promise((resolve,reject)=>{
            resolve("success")
        })
        const p2 = Promise.resolve("success")
        const p3 = Promise.reject("failed")

        p1.then(value => console.log(value))     	//success
        p2.then(value => console.log(value))     	//success
        p3.catch(reason => console.log(reason))     		//failed
		p3.then(value =>{},reason => console.log(reason))   //failed

		const pAll = Promise.all([p1,p2,p3])
        pAll.then(value=>{},reason=>{
            console.log(reason); //seccess
        })

		const pRace = Promise.race([p1, p2, p3])
        pRace.then(value=>{
            console.log(value);  //seccess  
        },reason=>{
            console.log(reason);       
        })

		const pRaceAgain = Promise.race([p3, p1, p2])
        pRaceAgain.then(value=>{
            console.log(value);   
        },reason=>{
            console.log(reason); //failed      
        })

从上面的代码中我们可以分析:p1和p2返回的都是一个成功的值为"success"的Promise对象,由此来理解Promise.resolve()这个简写形式(语法糖),然后p3返回的是一个失败的promise我们就可以通过调用catch或者then方法来拿到或者查看我们的PromiseValue。

pAll之所以返回的是失败的promise,是因为p3是失败了,不满足全都成功的条件。去掉p3就可以成功;pRace返回的是成功的Promise,因为他们都没有延时,而传入的第一个promise是成功的p1,因此最先完成的就是p1,因此返回的是成功的promise。

pAllAgain之所以失败,因为最先返回的是p3这个失败的promise。

注:因为p1,p2,p3都没有延时,都是同步的,所以谁在前race方法返回就由谁决定,如果有异步,延时,结果需要另外分析。

发布了28 篇原创文章 · 获赞 0 · 访问量 760
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览