当前位置:网站首页>Promise学习(三)Promise的几个关键性问题 -- 状态改变、执行顺序与机制、多任务串联、异常穿透、中断promise链
Promise学习(三)Promise的几个关键性问题 -- 状态改变、执行顺序与机制、多任务串联、异常穿透、中断promise链
2022-08-01 10:21:00 【對不起该用户已成仙】
目录
前言
问题一、Promise 状态的改变?
1. resolve 转为成功状态
resolve(value): 如果当前是pending就会变为fulfilled (resolved)
let p = new Promise((resolve, reject) => {
resolve('ok'); // pending => fulfilled (resolved)
});
console.log(p);
p.then(value => {
console.log(value);
}, reason => {
console.log(reason);
})

2. reject 转为成功状态
reject(reason): 如果当前状态是pending就会变为rejected
let p = new Promise((resolve, reject) => {
reject("err"); // pending => rejected
});
console.log(p);
p.catch(reason => {
console.log(reason);
})

3. 抛出异常转为失败状态
抛出异常: 如果当前是pending就会变为rejected
let p = new Promise((resolve, reject) => {
throw '出错了';
});
console.log(p);
p.catch(reason => {
console.log(reason);
})

注:对于上面的失败状态可以执行
catch 方法来处理失败的回调
问题二、一个 promise 指定多个成功/失败回调函数, 都会调用吗?
当 promise 改变为对应状态时都会调用,改变状态后,多个回调函数都会调用,并不会自动停止。简而言之,就是只要 promise 改变了状态,其绑定的所有回调函数都会调用执行。
let p = new Promise((resolve, reject) => {
// resolve('ok');
reject('err');
});
console.log(p);
// 指定回调-1
p.then(value => {
console.log('我是第一个回调:' + value);
}).catch(reason => {
console.log('我是第一个回调:' + reason);
});
// 指定回调-2
p.then(value => {
console.log('我是第二个回调:' + value);
}).catch(reason => {
console.log('我是第二个回调:' + reason);
});

可以看到失败状态下,两个失败回调都被catch方法处理好返回了,同理,成功时会调用then方法一样返回对应的回调结果。
问题三、改变 promise 状态和指定回调函数谁先谁后?
(1) 都有可能
正常情况下是先改状态再指定回调,但也可以先指定回调再改变状态
- 先指定回调再改变状态(
异步):先指定回调 => 再改变状态 => 改变状态后才进入异步队列执行回调函数 - 先改状态再指定回调(
同步):改变状态 =>指定回调并马上执行回调
(2) 如何先改状态再指定回调?
注意: 指定并不是执行
- ① 在执行器中直接调用 resolve()/reject() --> 同步操作
- ② 延迟更长时间才调用 then() -->在
.then()这个方法外再包一层例如延时器这种方法,异步操作
(3) 什么时候才能得到数据?
- 如果
先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据 - 如果
先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据 - 也就是说只有当状态改变后才能得到数据
下面我们例出一个 先指定回调后改变状态 的小案例:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('okk');
}, 1000);
});
const dp = p.then(value => {
console.log('最终的回调结果为:' + value);
},reason=>{
console.log(reason);
});
console.log(dp);


可以看到我们将p的回调赋给了dp,并且此案例延时了改变状态,所以它是先指定回调,后改变状态,但最终回调的结果还是为状态改变后的输出,由此可以得出结论:
只有当状态改变后才能得到数据
问题四、promise.then()返回的新 promise 的结果状态由什么决定?
答: 由 then() 指定的回调函数执行的结果决定
(1)如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
(2)如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
(3)如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
let p = new Promise((resolve, reject) => {
resolve('ok'); // 成功
});
// 执行then方法
let result = p.then(value => {
// console.log(value);
// 1. 抛出错误
// throw '出错了!'; // 失败 reject
// 2. 返回结果是非 Promise 类型的对象
// return 111; // 成功 fulfilled 结果为返回值
// 3. 返回结果是 Promise 对象
return new Promise((resolve, reject) => {
reject('error了')
})
}, reason => {
console.warn(reason);
});
console.log(result);

有三种情况,由上面的案例可知(第三种情况,前面两种情况在代码注释中可以看到,这里就不一一例举了),我们先把 promise 改变状态为
成功,然后往then方法里面传入失败状态的 promise 对象,最后的结果是根据then中的对象的状态来决定的。
问题五、promise 如何串连多个操作任务?
- promise 的
then()返回一个新的 promise, 可以看成then()的链式调用 - 通过
then 的链式调用串连多个同步/异步任务,这样就能用then()将多个同步或异步操作串联成一个同步队列
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve('success');
});
}).then(value => {
console.log(value);
}).then(value => {
console.log(value);
});
由上面可以得到,只有当
p的状态变为成功'ok'时,第一个then的成功回调才会执行,然后回调函数中的结果'success',当then的第一个回调promise 对象成功时,会继续执行下一个回调,因为第一个then的回调返回了一个promise 成功的对象,所以他的返回值会传入到第二个then的回调里面,所以第二个then的回调 中会输出'success',但第二个then的回调没有返回值,所以第三个then回调输出undefined。

问题六、promise 异常穿透
- 当使用
promise的then 链式调用时, 可以在最后指定失败的回调 - 前面任何操作出了异常, 都会传到最后失败的回调 catch() 中处理
可以在每个then()的第二个回调函数(reason)中进行err处理,也可以利用
异常穿透特性,到最后用catch去承接统一处理,两者一起用时,前者(reason)会生效(因为reason已经将其处理,就不会再往下穿透),走不到后面的catch
这里补充一下之前的知识点,then方法有两个回调函数形式的参数,前者(
value)代表成功的回调,后者(reason)代表失败的回调。
then 的第二个回调 reason 处理 err 如下:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('err')
}, 1000);
});
p.then(value => {
console.log(111);
}).then(value => {
console.log(222);
}).then(value => {
throw '出错啦!'
return value; // 将失败的值传入下一个then中
}).then (value => {
console.log(value);
}, reason => {
console.warn(reason); // 失败时回调
});
异常穿透 处理 err 方法如下:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
});
p.then(value => {
console.log(111);
}).then(value => {
console.log(222);
}).then(value => {
// console.log(333);
throw '出错啦!'
}).catch (reason => {
console.warn(reason);
});
最后都会得到以下输出

问题七、中断 promise 链
应用场景:有上面的问题二可知,当promise状态改变时,他的所有链式调用都会生效,那如果我们有这个一个实际需求:我们有3个 then(),假如其中有条件判断,不符合第一个 then() 条件时,要直接中断链式调用,不再运行调用下面的 then() ,解决方法如下。
- 当使用 promise 的
then链式调用时, 在中间中断, 不再调用后面的回调函数 - 办法: 在回调函数中返回一个
pendding状态的promise 对象
return new Promise(() => {});// 返回一个pending状态的Promise对象
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一个方式
// 返回一个pending状态的Promise对象
return new Promise(() => {
});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});

Authors: min
时间: 2022年7月26日
边栏推荐
- 【cartographer ros】十: 延时和误差分析
- Batch大小不一定是2的n次幂!ML资深学者最新结论
- ASP.NET Core 6 Framework Revealing Instance Demonstration [30]: Develop REST API with Routing
- Qt 支持HEIC/HEIF格式图片
- Generate certificates using KeyStore
- Google Earth Engine——给影像添加一个属性对于单景的时间序列并返回影像
- Taobao commodity details and details on taobao, senior upgrade version of the API
- 退役划水
- 2022年7月31日--使用C#迈出第一步--使用C#中的数组和foreach语句来存储和循环访问数据序列
- STM32入门开发 介绍IIC总线、读写AT24C02(EEPROM)(采用模拟时序)
猜你喜欢

Change Servlet project to SSM project

Py之yellowbrick:yellowbrick的简介、安装、使用方法之详细攻略

rpm and yum

What is a stepper motor?40 pictures to show you!

如何从完美的智能合约中窃取 1 亿美元

Enterprise WeChat group: robot timing reminder function database configuration

Yang Hui Triangle (C language implementation)

50.【Application of dynamic two-dimensional array】

Qt 支持HEIC/HEIF格式图片

回归预测 | MATLAB实现TPA-LSTM(时间注意力注意力机制长短期记忆神经网络)多输入单输出
随机推荐
Drawing arrows of WPF screenshot control (5) "Imitation WeChat"
July 31, 2022 -- Take your first steps with C# -- Use arrays and foreach statements in C# to store and iterate through sequences of data
CTFshow,命令执行:web33
分类预测 | MATLAB实现1-DCNN一维卷积神经网络分类预测
[Cloud Residency Co-Creation] Huawei Cloud Global Scheduling Technology and Practice of Distributed Technology
我是如何保护 70000 ETH 并赢得 600 万漏洞赏金的
【钛晨报】国家统计局:7月制造业PMI为49%;玖富旗下理财产品涉嫌欺诈,涉及390亿元;国内航线机票燃油附加费8月5日0时起下调
How to find out hidden computer software (how to clean up the computer software hidden)
机器学习 | MATLAB实现支持向量机回归RegressionSVM参数设定
Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (2) Mini Program Functions
如何在IntellJ IDEA中批量修改文件换行符
【cartographer ros】十: 延时和误差分析
Glassmorphism design style
世界第4疯狂的科学家,在103岁生日那天去世了
正则表达式
Generate certificates using KeyStore
What's up with VS "Cannot find or open PDB file"?How to solve
The first experience of Shengsi large model experience platform——Take the small model LeNet as an example
Meeting OA (Upcoming Meetings & All Meetings)
MySQL常用语句总结