参考网址在这里。地址。
目录
3.3 Promise只能在resolve, reject中选择一个来执行
11.4 then方法返回的Promise实例对象的状态由谁决定?
文件操作,ajax操作,数据库操作,定时器操作。总结就是:涉及I/O和网络这种费时的操作都是异步操作,因为js主线程执行代码都是ms级的,等不了秒级的操作,从而提升运行效率。
在各种异步编程解决方案出现之前,也急速最原始的时候,都是使用回调函数解决异步编程。所谓回调函数就是指:异步需要花时间完成,那么完成之后将得到的数据交给回调函数处理。
工程上,任何事物的出现都是解决一定的实际问题。promise的出现也是一样的。他解决了回调地狱的问题,但是简化了语法,减少了代码量,易于读懂。
回调地狱是指:多个异步操作之间存在依赖关系,如:操作4需要操作3的结果,操作3需要操作2的结果,操作2需要操作1的结果。这样的话就嵌套了四层函数。
1,语法简单;2,支持异常处理;3,支持链式调用;4,可以为一个返回结果设置多个处理函数(回调函数)。
启动异步任务=>返回promie对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)。
语法规定的,没有为什么。
已知Promise构造函数的参数是一个函数,作为参数的这个函数也具有两个参数,分别是:resolve, reject。他们由js解析引擎提供,我们不能更改其名字。
他们的主要作用就是将异步操作的结果返回,并设置当前Promise实例对象的真假状态。Promise实例对象有一个then()方法,会根据真假状态执行不同的回调函数。
文件操作,ajax操作,数据库操作,定时器操作等的一般结果就是:得到结果和没得到结果。如果得到结果则为true则执行resolve并将当前Promise实例对象的状态设为真,没有得到结果则为false则执行reject并将当前Promise实例对象的状态设为假。
到底是true还是false,需要业务逻辑来决定。
如果不使用异步,让CPU将程序挂起2s,这将毫无用户体验。最佳的做法:将这个函数变为异步函数,先让主线程执行完毕必要的代码,再来处理这个耗时的函数。
下面的程序1-30之间为中奖。
- //生成随机数
- function rand(m, n) {
- return Math.ceil(Math.random() * (n - m + 1)) + m - 1;
- }
- //建立task,下面会将这个task传给Promise,f的参数必须为resolve, reject不能改变,resolve, reject是两个函数
- f = (resolve, reject) => {
- //定时器
- setTimeout(() => {
- //获取从1 - 100的一个随机数let n = rand(1,100);
- let n = rand(1, 100);
- //判断
- if (n <= 30) {
- resolve();
- } else {
- reject();
- }
- }, 2000)
- }
-
- //创建Promise实例对象
- reward = new Promise(f); //将参数f传给Promise,但是这个函数f必须保持特殊格式
-
- //如果resolve被执行,Promise的实例对象reward的状态为真,则会执行f1
- //如果reject被执行,Promise的实例对象reward的状态为假,则会执行f2
- reward.then(
- f1 = (data) => console.log('恭喜恭喜,奖品为10万 RMB 劳斯莱斯优惠券', `中奖号码为${data}`),
- f2 = (data) => console.log('再接再厉', `中奖号码为${data}`)
- )
util.promisify方法提供一种主动返回Promise实例对象的解决方法。我们将异步操作函数作为参数传给util.promisify,他就会返回一个实例对象给我们,而且对失败的这种形式进行了优化处理,十分的方便。语法格式:util.promisify(异步操作函数名)。
Promise实例对象的属性PromiseState记录着状态。
pending:在没有执行resolve和reject函数之前就是pending,也就是异步操作还没有完成,结果还没有拿到。
resolved:成功拿到结果,resolve被执行。
rejectd:没有拿到结果,业务逻辑决定执行reject函数。
这个属性的值由resolve和reject函数进行修改。然后PromiseResult属性值(可能是任何类型的)被then方法中回调函数进行处理。
传给Promise构造函数的那个作为参数的函数就是执行器。
重点:这个方法的返回结果也是一个Promise实例对象,这是链式调用的基础。
类似于异常捕捉。他只能响应rejectd状态的情况。如果异步操作无法拿到结果的时候,需要进行大量处理,则可以把大量代码写在catch方法里面。
无论什么传入什么参数,直接返回一个失败的promise对象。而且会将传入参数直接作为PromiseResult属性的值。
他的参数是一个数组,但是每一个数据元素都必须是Promise实例对象。
上面状态指的是p1,p2,p3的PromiseResult属性。
如果p1,p2,p3中p1失败了,则result是一个失败的Promise实例对象,他的PromiseResult属性值是p1的PromiseResult属性。
当为resolved状态设置多个回调函数该怎么办?
先改状态再回调:直接同步运行resolve或者reject函数即可。或者给then加上定时器延时执行。
先回调再改状态:将resolve或者reject函数放在异步操作里面即可。
当链式调用中的某一环节出现异常该怎么处理?在链式调用的尾巴处加上catch方法即可。异常穿透是指出现异常则结束链式调用去执行错误处理函数。
在链式调用中将某一个Promise实例对象的PromiseState置为pending即可。