javaScript中Promise简单介绍和理解

1、Promise是什么

Promise是异步编程的一种解决方案。Promise本身是一个对象(一个构造函数),从它可以获取异步操作信息。主要处理回调地狱、异步的问题。

Promise有三种状态,pending(等待状态),fulfilled(成功状态),rejected(失败状态)。

Promise还有state属性和result属性,state值是当前状态值,result值是当前结果值。

新建一个promise实例:

此时,可以看到Promise是一个对象,里面有PromiseState和PromiseResult属性,state属性的value值是当前promise的状态(pending),result的值是当前promise的结果值。

可以看到new Promise 的时候,有两个参数,resolve和reject,这两个参数是两个函数,resolve是promise成功时执行的函数(此时promise状态变为fulfilled),reject是promise失败是执行的函数(此时promise状态变为rejected)。并且当promise的状态发生改变之后,promise状态不会再发生改变(可自行多添加几个resolve或reject测试)。当执行resolve和reject时,下面可以看到promise的状态变化。

此时promise状态变为rejected,提示警告,未捕获到这个失败。

总结:promise的三种状态:pending状态 fulfilled状态 rejected状态

创建promise时,此promise状态为pending,他的result值为undefined

当调用resolve或reject时,promise的状态发生改变

resolve('成功') 此时promise状态为fulfilled,result值为resolve返回值就是'成功'

reject('失败') 此时promise状态为rejected,result值为reject返回值就是'失败'

*promise的状态一经改变,就不会再发生改变

2、Promised中的.then(),.catch(),.finally()方法

上面我们看到,当promise状态为rejected时,有一条警告,提示未捕获到'失败'在promise中,下面开始介绍Promise的.then()方法,用于捕获警告和抛出的错误。

*当promise状态发生改变的时候,就会执行.then()方法,相反,状态没有发生改变的时候.then()就不会执行

(1).then()

.then((value)=>{console.log(value)},(error)=>{console.log(error)})

可以看出,.then()方法传两个参数,分别是两个回调函数,第一个是promise状态变为fulfilled时执行的回调,第二个时状态变为rejected时执行的函数,value值是成功、失败的结果值。


const myPromise = new Promise((resolve, reject) => {
            console.log('promise实例');
            resolve('成功')
            // reject('失败')
        })
        console.log(myPromise);
        myPromise.then((value) => {
                console.log('value',value);
            },
            (error) => {
                console.log(error);
            })

结果:

当放开rejected,注释调resolve时。此时可以看到没有那条警告了,.then()的第二个参数捕获到reject的抛出的错误警告,并获取到返回值,也就时error的值。

另外:promise的这些方法也是可以进行链式调用的,比如:


 const myPromise = new Promise((resolve, reject) => {
            console.log('promise实例');
            resolve('成功')
            // reject('失败')
        })
        console.log(myPromise);
        myPromise.then((value) => {
                console.log('value', value);
                return 2
            },
            (error) => {
                console.log(error);
            }).then((value) => {
            console.log(value);
        })

结果:

此时,.then()里面的回调return一个值的时候,这个值不是promise对象,就会自动将这个值包裹成promise对象,例:return 2 --> return Promise.resolve('2')

.then()和.catch()的return都会返回一个新的promise对象

。返回结果是一样的。.catch中也是如此。但是如果抛出错误时,需要return Promsie.reject('3')或者 throw new Error('3')。此时可自行打印查看结果,下面会提到:

(2).catch()

.catch((error)=>{console.log('error',error)})

它的作用是,可以捕获上层未能捕获到的错误,

例:


 const myPromise = new Promise((resolve, reject) => {
            console.log('promise实例');
            // resolve('成功')
            reject('失败')
        })
        console.log(myPromise);
        myPromise.then((value) => {
            console.log('value', value);
            return 2
        }, ).then((value) => {
            console.log(value);
        }).catch((error) => {
            console.log('error', error);
        })

此时,我们看,第一次.then()时,没有传递第二个参数,所以未捕获错误,第二次.then()同样没有传递第二个参数,也未捕获错误,在.catch的时候,捕获到错误。

此时我们看一下如何进行抛出错误:


const myPromise = new Promise((resolve, reject) => {
            console.log('promise实例');
            resolve('成功')
            // reject('失败')
        })
        console.log(myPromise);
        myPromise.then((value) => {
            console.log('value', value);
            return new Error('11')
            // throw new Error('11')
            // return Promise.reject('11')
        }, ).then((value) => {
            console.log(value);
        }).catch((error) => {
            console.log('error', error);
        })

第9行,第10行,第11行,

第9行结果:

第10、11行结果:(在.catch()中捕获到错误,并打印error。印证上述黄色背景描述结论)

(3).finally()

.finally(()=>{console.log('222')})

.finally()方法,不需要传递参数,只要promise状态改变的时候,就会执行,无论状态变为fulfilled还是rejected。

例:


 const myPromise = new Promise((resolve, reject) => {
            console.log('promise实例');
            resolve('成功')
            // reject('失败')
        })
        console.log(myPromise);
        myPromise.then((value) => {
            console.log('value', value);
            return 1
        }, ).then((value) => {
            console.log(value);
        }).catch((error) => {
            console.log('error', error);
        }).finally(() => {
            console.log('something');
        })

在实际应用中可能会碰到一些上述没总结到的情况,请评论。

3、Promise中的all()和race()方法

共同点,两个方法都是接收一组异步任务,并行执行异步任务,

不同点:.all():在所有异步任务执行完成之后在执行回调,(异步任务全部完成,会在一个回调里处理全部数据,如果,异步任务中,有一个执行失败,那么就不会执行这个处理结果的回调)

.race():只保留第一个异步任务完成的结果,其他异步任务仍然执行,但是结果不保留,(不会放在成功的回调里。)

例:


//函数1
function runAsync(x) {
    let p = new Promise((resolve) => {
           setTimeout(() => {
               resolve(x)
               console.log(x);
            }, 1000);
        })
     return p
}

//失败函数  函数2
function runReject(x) {
            let p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject(x)
                    console.log(x);
                }, 1000 * x);
            })
            return p
        }
(1).all()

执行多个函数1时


Promise.all([runAsync(1), runAsync(2), runAsync(3), runAsync(4)]).then((res) => {
            console.log('res', res);

结果:同时打印1234和res

如果:异步任务中出现失败的情况,(添加runReject函数)


 Promise.all([runAsync(1), runReject(2), runAsync(3), runReject(4)]).then((res) => {
            console.log('res', res);
        })

结果:1、3同时打印,2秒后打印2,报错,4秒后打印4

2秒的时候,报错,此时我们添加.catch捕获异常


Promise.all([runAsync(1), runReject(2), runAsync(3), runReject(4)]).then((res) => {
            console.log('res', res);
        }).catch((err) => {
            console.log('err', err);
        })

结果:顺序和上面相同,报错被捕获到。但是下面的4的错误为什么没有被捕获到呢?

总结:.catch()函数能够捕获到.all()里最先的那个异常,并且只执行一次。

而且此时,没有了那个res的返回值。没有执行.then()的第一个回调。

(2).race()

执行多个函数1时


Promise.race([runAsync(1), runAsync(2), runAsync(3), runAsync(4)]).then((res) => {
            console.log('res', res);
        }).catch((err) => {
            console.log('err', err);
        })

结果:1s后同时打印,但是,只有1个是从.then()中返回的。所以他是只保留第一个执行完成的结果,其他的异步仍然执行,但是,不会保留在执行成功的回调里了。

当异步任务中出现失败的情况,我们看下:


Promise.race([runAsync(1), runReject(2), runAsync(3), runReject(0)]).then((res) => {
            console.log('res', res);
        }).catch((err) => {
            console.log('err', err);
        })

结果:0秒打印0 和.catch里面的返回值,1s后,打印1、3,2s后打印2

总结:all和race传入的数组中如果有会抛出异常的异步任务,那么只有最先抛出的错误会被捕获,并且是被then的第二个参数或者后面的catch捕获;但并不会影响数组中其它的异步任务的执行

(3).allSettled方法

接受一个promise数组作为参数,同时开始,并行执行。

但是:.allSettled方法不会走进.catch,当所有的promise执行完成之后,无论成功或者失败,都会解析出一个具有完整状态的数组。

.all是:(同时开始,并行执行)数组全部执行完成,才会统一在一个回调里面返回值,如果有一个是失败状态,则没有返回值。

.race:数组全部执行,最先执行完成的那个(且状态是成功),执行一次回调函数,该回调是最先执行完成的值,其他数组异步继续执行。

4、事件循环、宏任务、微任务之间的顺序和关联

首先,宏任务和微任务都是异步任务

一段代码执行的时候,先执行同步任务,再执行宏任务,再执行微任务

队列:供任务队列和微任务队列

微任务队列为空的时候才会进入下一次循环,即执行下一个宏任务,依次循环,直到宏任务、微任务列表都为空,执行完毕。(宏任务、微任务中遇到同步任务时,肯定先执行同步任务)

常见的宏任务:script、setTimeout、setInterval、setImmediate 、I/O 、UI rendering

常见的微任务:Promise.then()或catch(),MutationObserver,Node独有的process.nextTick,

事件循环执行顺序

最开始整个脚本(script标签)作为一个宏任务执行

执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列

同步代码执行完毕后,执行栈为空,(因为第一个宏任务是script,第一次的宏任务已经执行完毕)开始执行检查微任务队列,执行微任务,直到微任务列表为空,再执行下一个宏任务。依次循环,直到宏任务队列和微任务队列为空。

例1:


 console.log('11');
        const myPromise = new Promise((resolve, reject) => {
            console.log('12');
            resolve('13')
        })

        console.log('14');
        myPromise.then((value) => {
            console.log('15');
            console.log('value', value);
        })
        console.log('16');

结果:

详细讲解:脚本作为第一个执行文件开始执行,他是一个宏任务,此时宏任务队列:宏:【script】

首先打印11

然后12 (new Promise内部是一个立即执行函数,可以当做为同步任务,所以立即打印)

然后执行resolve(‘13’),此时promise状态改变,

跳出new Promise构造函数,

打印14

遇到.then(),他是一个微任务,进入微任务队列,此时的微任务队列:微:【.then()】

打印16

此时,第一轮的同步任务执行完毕,第一轮的宏任务(script)也执行完毕,开始检查微任务队列,有一个.then(),执行函数,打印15,然后打印13,检查宏任务、微任务列表,都为空,事件循环执行完毕。

例2:


        console.log('11');
        const myPromise = new Promise((resolve, reject) => {
            console.log('12');
            setTimeout(() => {
                resolve('13')
                console.log('21');
            }, 0)
            console.log('22');
        })

        console.log('14');
        myPromise.then((value) => {
            console.log('value', value);
            return 5
        }).then((value) => {
            console.log('thenvalue', value);
            setTimeout(() => {
                console.log('settimeout');
            }, 0)
        })
        console.log('16');

结果:

这个,外面的顺序和第一个差不多,,就是新添加了setTimeout,和链式调用了.then(),

大家可以自行判断答案,如有问题,牢记(微任务队列为空的时候,才会进入宏任务队列执行下一个宏任务,也就是说,一个宏任务可能后面跟好几个微任务队列)。

5、附言

本文也是总结出来的,经过判断和验证,应该没有问题,如有问题,请直接提出来!事件循环的内容实际还很多,这里大概解释了过程,用于判断执行先后顺序完全可以。加油~

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
JavaScriptPromise是一种处理异步操作的方法。它可以将异步代码以更直观和可读的方式进行组织和管理。 Promise是一个代表着未来完成或失败的操作的对象。它有三个状态:pending(进行)、fulfilled(已完成)和rejected(已拒绝)。当一个异步操作开始执行时,Promise会处于pending状态,然后根据操作的结果转变为fulfilled或rejected状态。 你可以使用Promise构造函数创建一个新的Promise对象。它接受一个带有两个参数的函数作为参数,这两个参数分别是resolve和reject。resolve函数用于将Promise状态从pending转变为fulfilled,而reject函数用于将其转变为rejected。 下面是一个简单的示例,展示了如何使用Promise处理异步操作: ```javascript const myPromise = new Promise((resolve, reject) => { // 异步操作 setTimeout(() => { const isSuccess = true; if (isSuccess) { resolve("操作成功"); } else { reject("操作失败"); } }, 2000); }); myPromise.then((result) => { console.log(result); // 打印: 操作成功 }).catch((error) => { console.log(error); // 打印: 操作失败 }); ``` 在上面的示例,我们创建了一个Promise对象`myPromise`,并在2秒后模拟了一个异步操作。如果操作成功,我们调用resolve函数并传递一个成功的消息;如果失败,我们调用reject函数并传递一个失败的消息。 然后,我们使用`then()`方法来处理Promise的fulfilled状态,并使用`catch()`方法来处理rejected状态。这些方法可以链式调用,以便处理多个异步操作的结果。 这只是Promise的基本概念和用法,它还有很多其他功能和方法,比如`Promise.all()`和`Promise.race()`等。希望这个简单的示例能帮助你理解JavaScriptPromise

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值