傲娇大少之--Promise

liao一下promise

先来一碗毒鸡汤润润喉:
不要以为世界抛弃了你,世界根本没空搭理你!吼吼~

promise /ˈprɒmɪs/ 【许诺,承诺】

关于promise之前也有各种开源的写法,在ES6中被规范化,更加的受广大前端开发工程师所喜爱。

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。我们通过创建该构造函数的对象来执行异步操作。嗯~大概就是酱紫:

let pp = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok!!');
	}, 2000);
}).then(resolve){ // 异步函数执行成功
	console.log(resolve);
}.catch(reject){ // 异步函数执行失败
	console.log(reject);
};

分开看就是先创建一个实例,然后调用实例继承的Promise类的方法then和catch等。

let pp = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve('ok!!');
	}, 2000);
})// 执行异步函数成功
pp.then((resolve) => {
	console.log(resolve);
});

// 异步函数执行失败
pp.catch((reject) => {
	console.log(reject);
});

这就是promise的基本写法。
很疑惑的是都说promise是实现异步的函数,那为啥在promise里面都要再写个异步的setTimeout之类的函数呢?那么问题来了,promise里面的内容,真的是异步吗?我们做个小小的例子看一下:

console.log(111111);
let pp = new Promise((resolve, reject) => { // 定义一个promise的实例对象
	console.log(222222);
});
console.log(333333);

假如promise是异步的,那么执行结果,必然是:111111 =》 333333 =》 222222。我们执行一下,看执行结果:
在这里插入图片描述
竟然是乖乖的顺序执行的,也就是说promise是同步的!!

那么问题又来了,为啥大家都说promise是实现异步的呢?
看例子:

let pp = new Promise((resolve, reject) => {
	resolve(555555);
});
console.log(444444)
pp.then((resolve) => {
	console.log(resolve);
});
console.log(666666);

直接看结果:
在这里插入图片描述
说明了什么?promise的then是异步的,也就是说真正实现异步的是then()!!

所以分析一哈,promise的内容是顺序执行的,调用then方法的时候才真正的实现了异步。而在实际开发过程中,我们一般会在promise中执行比较复杂的函数比如调用接口之类的,then用来处理回调。所以为了提高效率,我们普遍会在promise内部使用异步函数。

关于promise:

promise有三个状态:pendingfulfilledrejected
用白话说就是promise里面定义的内容的执行状态,也可以理解为resolve的结果的完成状态。

  1. pending /ˈpendɪŋ/ 【待定,悬而未决】在这里,我们理解为正在执行中。
  2. fulfilled /fʊlˈfɪld/ 【实现,履行】在这里,我们理解为执行成功。
  3. rejected /rɪˈdʒektɪd/ 【拒绝接受,不予考虑】在这里,我们理解为执行失败了。

promise有且只有上面三种状态,我们可以根据这几种状态的含义,很清晰的能分辨出状态的变换过程,只有两种:

  1. pending =》fulfilled :执行成功,resolve被赋值。
  2. pending =》rejected:执行失败,rejected被赋值。

而且这两种状态的变化是不可逆的,一旦发生改变后,状态就凝固了,我们叫它resolved(已定型)。也就是说resolve或者reject被赋值之后,就固定了,不会再变化了,后续调用promise对象的then或catch方法时,只是拿resolve或reject的值进行一些需要的操作而已。

比如我们把promise的回调函数写在一个click事件里面:

let i = 0;
let pp = new Promise((resolve, reject) => {
	setTimeout(() => {
		resolve(i++);
	}, 2000);
})let btn = document,getElementById('button');
btn.onclick = function () {
	pp.then((resolve) => {
		console.log(resolve);
	});
};

我们知道这个id为button的按钮每点击一次,必然会在控制台上打印一次,但是结果是0,1, 2,3,4吗?并不是,如果你真实的实践一次,会发现每次点击按钮,打印的都是0!
这就用事实论证了上面状态不可逆的问题。执行了就是执行了,绝不会再执行一次,resolve被赋值后会一直给你保留着,随时都可以使用。就是说无论你什么时候调用then的时候,都可以拿到这个resolve的值。
在这里插入图片描述
现在,知道了promise的三种状态的变化,我们再来分析一下promise常用的方法:then(),catch(),all(),race()。

在上面我们讲解的过程中,一直在调用then和catch这两个方法,这两个方法也是我们在使用promise的过程中出现最多的两个方法,意思就是执行成功和执行失败的回调函数,这里就不多说了。

主要说一下all() 和 race()

  1. all():顾名思义,all 全部。之前我们理解的then()是一个promise执行成功的回调,那如果我想要多个promise都执行成功后再进行回调,all就派上用场了。用法如下:
function p1 ()  {
	return new Promise((resolve) => {
		console.log('p1');
		resolve('p11');
	});
}
function p2 ()  {
	return new Promise((resolve) => {
		console.log('p2');
		resolve('p22');
	});
}
function p3 ()  {
	return new Promise((resolve) => {
		console.log('p3');
		resolve('p33');
	});
}

let btn = document,getElementById('button');
btn.onclick = function () {
	Promise.all([p1(), p2(), p3()]).then((results) => {
		console.log(results);
	});
};

结果:
p1
p2
p3
[“p11”, “p22”, “p33”]

综上所述:all函数是由Promise类调用,且参数为数组,数组元素为promise对象,回调函数中参数为所有promise的resolve值组成的数组。嗯嗯~就酱紫。

  1. race():用法与all相同,含义与all相反,all是等所有promise全部执行成功后,才执行回调函数,而race是只要有一个promise对象执行成功就执行回调,用法如下:
let pp1 = new Promise(resolve => {
    setTimeout(() => {
        console.log('p1');
        resolve('p11');
    }, 500);
});
let pp2 = new Promise(resolve => {
    setTimeout(() => {
        console.log('p2');
        resolve('p22');
    }, 200);
});
Promise.race([pp1, pp2]).then((results) => {
    console.log(results);
});

执行结果:
p2
p22
p1

根据setTimeout可以看出p2会优先于p1先执行完成,所以race会在p2执行完成后,直接出发回调,打印出的结果为:p2 和 p22
然后,因为pp1已经定义了且promise是同步的,所以p1也会在500毫秒延时结束时,成功的打印出来。

到这里,我们对promise的理解应该就比较透彻了, 三种状态,两种状态变化,四个方法这三个重点理解透彻了,就很简单了。

拓展

其实提到异步,脑海中蹦出了一堆东西,像什么setTimeout,setInterval什么的,现在我们来分析一下promise和setTimeout之间的一些小猫腻。

let pp = new Promise((resolve) => { // 定义一个promise独对象
	resolve(123456);
});

setTimeout(() => {
	console.log('setTimeout 的异步执行!');
}, 0);

pp.then(resolve => {
	console.log('promise 的异步!');
});

你猜,你猜,结果是谁先?

执行结果:
promise 的异步!
setTimeout 的异步执行!

神奇不?经过上边的分析,我们知道promise的then是异步的,而setTimeout也是异步的,且我们设置的延时时间为0。
按道理说,大家都是异步也的按执行完成的时间顺序来吧。为啥promise的then有优先权呢?

这就要从JavaScript的异步原理说起了,都说JavaScript是单线程的,也就是说JavaScript有一个主线程task在处理逻辑。

setTimeout的异步呢,就是会重新创建一个新的线程task去执行异步的逻辑,叫做宏任务。
promise虽然也是异步,但它没有重新开启一个新的线程,而是一个微任务(micro task)。

大家都知道JavaScript的异步就是主线程执行结束后,去异步任务的回调队列中去查看,是否有执行完成的异步回调,如果有就执行。

这两种异步执行结束之后,都会乖乖的到任务队列中去排队,等待主线程的宠幸。不同点在于setTimeout的宏任务会到宏任务队列中去排队,而promise微任务会到微任务队列中去排队。

主线程会先宠幸自己的微任务,然后再宠幸宏任务。

所以promise会优先于setTimeout执行。这个还是要重点关注下的,现在很多公司都会用这个问题做为面试题,所以了解一下肯定没错的啦~

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redux Promise是一个Redux中间件,它的作用是派发一个Promise对象,并且可以通过参数resolve来触发一个action。通过创建一个Promise实例,我们可以在resolve中定义想要派发的action的类型和payload。这样做的好处是可以更方便地处理异步逻辑,例如在异步请求返回后再派发相应的action来更新状态。 如果你想在你的Redux应用中使用Redux Promise中间件,可以通过npm安装@tracktl/redux-promise-middleware包,或者在你的项目中添加@tracktl/redux-promise-middleware作为依赖。然后你可以在Redux的store中使用applyMiddleware来将Redux Promise中间件添加到中间件链中。 在众多Redux中间件中,处理Redux异步事件的中间件占据了重要的地位。从简单的redux-thunk到redux-promise再到redux-saga等等,它们都提供了各自的解决方案来管理Redux异步流。对于redux-promise来说,它通过Promise对象的特性,让我们可以更加简洁地处理异步逻辑,并且将派发action的过程与异步操作分离开来。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [眼花缭乱的redux中间件,也不过如此](https://blog.csdn.net/dear_mRZhou_/article/details/118529380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [redux-promise-middleware:声明式Redux Prom中间件](https://download.csdn.net/download/weixin_42137032/16719421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Redux中间件(redux-thunk、redux-promise、redux-saga)](https://blog.csdn.net/yrqlyq/article/details/119243072)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值