当前位置:网站首页>【promise一】promise的介绍与手撸的关键问题
【promise一】promise的介绍与手撸的关键问题
2022-06-27 03:18:00 【翼遥bingo】
寒假看到现在的promise,为了准备面试,必须给个结尾,手撸真的难为窝了
一定node.js的基础
一、 Promise介绍与基本使用
1-1 介绍
概念
- Promise是一门新的技术
- Promise是JS中进行异步编程的新解决方案
- 备注: 之前是单纯使用回调函数
具体:
- 语法上: Promise是一个构造函数
- 功能 : promise对象用来封装一个异步操作并可以获取其成功/失败的值
异步编程
fs 文件操作
require('fs').readFile('./index/html',(err,data) => { })数据库操作
AJAX
$.get('/server',(data) => { })定时器
setTimeout(() => { }, 2000);
1-2 为啥要用Promise
- 指定回调函数的方式更加灵活
- 旧的: 必须在启动异步任务前指定
- promise : 启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
- 支持链式调用,可以解决回调地狱问题
- 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
- 回调地狱的特点 :
- 不便于阅读
- 不便于异常处理
1-3 Promise初体验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise请求抽奖界面</title>
</head>
<body>
<div class="container">
<div class="page-header">Promise初体验</div>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
// 生成随机数
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1) + m - 1);
}
/* 点击按钮, 2 s后显示是否中奖( 30 % 概率中奖) 若中奖弹出 恭喜 若未中奖弹出 再接再厉 */
// 获取元素对象
const btn = document.querySelector('#btn');
// 绑定单击事件
btn.addEventListener('click', function() {
// setTimeout(() => {
// // 30%, 1-100 1 2 30
// // 获取从1-100的一个随机数
// let n = rand(1, 100);
// // 判断
// if (n <= 30) {
// alert('恭喜恭喜');
// } else {
// alert("zaijiezailin");
// }
// }, 1000)
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 30%, 1-100 1 2 30
// 获取从1-100的一个随机数
let n = rand(1, 100);
// 判断
if (n <= 30) {
resolve(); // 将promise对象的转台设置为成功
} else {
reject(); // 将promise对象的状态设置为失败
}
}, 1000)
});
// 调用then方法
p.then(() => {
alert('恭喜恭喜,奖品为10万');
}, () => {
alert('再接再厉');
})
})
// Promise 形式实现
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
</script>
</body>
</html>
1-4 fs读取文件
1-5 Ajax请求
二、Promise封装
2-1 Promise封装fs模块
/* 封装一个函数 mineReadFile 读取文件 参数: path 文件路径 返回: promise 对象 */
function mineReadFile(path) {
return new Promise((resolve, reject) => {
// 读取文件
require('fs').readFile(path, (err, data) => {
// 判断
if (err) reject(err);
// 成功
resolve(data);
})
})
}
mineReadFile('./content.txt')
.then(value => {
// 输出文件内容
console.log(value.toString());
}, reason => {
console.log(reason);
})
2-2 util.promisify(original)【没懂】
- original
<Function>
- original
传入一个遵循常见的优先错误的回调风格的函数(即以(err,value) => …回调作为最后一个参数),并返回一个返回promise 的版本
2-3 封装 Ajax请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise封装Ajax请求</title>
</head>
<body>
<!-- 封装一个函数sendAJAX发送 GET AJAX 请求
参数 URL
返回结果 Promise 对象 -->
<script>
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
// 处理结果
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(error);
}
}
}
})
}
sendAJAX('https://netease-cloud-music-api-crete722p-hannah-bingo.vercel.app/user/detail?uid=32953014')
.then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
</script>
</body>
</html>
三 、 Promise对象属性介绍,工作流程…

3-1 Promise的状态【PromiseState】
promise的状态改变
pending变为resolved (成功的结果数据称为value)
pending变为rejected (失败的结果数据称为reason)
promise中的状态 : 指的是实例对象中的一个属性
[PromiseState]- pending 未决定的
- resolved / fullfilled 成功
- rejected 失败
3-2 Promise对象 的 值【PromiseResult】
- 实例对象中的另一个属性 【PromiseResult】
- 保存着对象[成功/失败的结果]
- reject
- resolve
3-3 Promise的工作流程

3-4 Promise的API
3-4-1 构造函数-then-catch
Promise 构造函数
Promise(excutor){}- executor 函数 : 执行器 (resolve, reject) => {}
- resolve 函数 : 内部定义成功时我们调用的函数 value => {}
- reject 函数 : 内部定义失败 时 我们调用的函数 resaon => {}
说明 : executor 会在 Promise内部立即同步调用 ,异步操作在执行器中执行
<script> let p = new Promise((resolve, reject) => { // 同步调用的 console.log(111); }) console.log(22); </script> // 结果: 111 22Promise.prototype.then方法 : (onResolved, onRejected)=> {}- onResolved 函数 : 成功的回调函数 (value) => {}
- onRejected函数 : 失败的回调函数 (reason) => {}
指定用于得到成功value 的成功回调和 用于得到失败reason的失败回调,返回一个新的promise对象
Promise.prototype.catch 方法 :(onRejected) => {}
onRejected 函数 : 失败的回调函数 (reason) => {}
<script> let p = new Promise((resolve, reject) => { reject('error'); }) p.catch(reason => { console.log(reason); }) </script>
3-4-2 函数对象,非实例对象 :resolve,reject,all,race方法
Promise.resolve 方法 : (value) => {}
value : 成功的数据或者promise对象
返回一个成功/失败的promise对象
<script> let p1 = Promise.resolve(521); // 如果传入的参数为非Promise类型的对象,则返回的结果为 成功promise对象 // 如果传入参数为Promise对象,则参数的结果决定了 resolve的结果 let p2 = Promise.resolve(new Promise((resolve, reject) => { resolve('ok'); })) console.log(p1); console.log(p2); </script>
Promise.reject方法 : (reason)=> {} 【快速返回失败的promise对象】
reason : 失败的原因
返回一个失败的promise对象
<script> let p = Promise.reject(521); console.log(p); </script>
Promise.all方法 : (promises) => {}
- promises : 包含n个promises的数组
- 返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败
<script> let p1 = new Promise((resolve, reject) => { resolve('OK'); }) let p2 = Promise.reject('EEE'); let p3 = Promise.resolve('Oh Yeah'); const result = Promise.all([p1, p2, p3]); const reject = Promise.all([p1, p3]) console.log(result); console.log(reject); </script>Promise.race方法 : (promises)=> {}
- promises : 包含n和promise 的数组
- 返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
四、Promise关键问题
4-1 如何修改promise对象 的状态
resolve(value) : 如果当前是pending 就会变成 resolved
reject(reason) : 如果当前是pending就会变成 rejected
抛出异常 : 如果当前是pending 就会变成rejected
<script> let p = new Promise((resolve, reject) => { // 1. 通过调用resolve函数 // resolve('ok'); // pending => fulfilled(resolved) // 2. reject函数 // reject("error"); // pending => rejected // 3. 抛出错误 throw "出问题" }); console.log(p); </script>
4-2 一个promise指定多个成功/失败回调函数【then方法】,能否执行多个回调?
- 当Promise改变为对应状态时 , 都会调用
<script>
let p = new Promise((resolve, reject) => {
// 改变状态
resolve('OK');
})
// 指定回调 -1
p.then(value => {
console.log(value);
})
// 指定回调 -2
p.then(value => {
alert(value);
})
</script>
4-3 改变promise状态与指定回调函数 的顺序问题
都有可能,正常情况下是 先指定回调函数 再改变状态,但也可以先改变状态 在指定回调
如何先改变状态在指定回调
在执行器中直接调用 resolve(), reject()
延迟 更长时间才调用 then()
<script> let p = new Promise((resolve, reject) => { // resolve("ok"); // 异步任务,先执行的回调 setTimeout(() => { resolve('OK'); }, 1000) }) p.then(value => { console.log(value); }, reason => { }) </script>
啥时候得到数据
- 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
- 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
4-4 then 方法返回结果由什么决定
- 由then() 指定的回调函数执行的结果决定
- 如果抛出异常,新promise变为rejected,reason为抛出的异常
- 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
- 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
- promise如何串联多个操作任务
- promise的then()返回一个新的promise,可以开发then()的链式调用
- 通过then的链式调用 串连多个同步/异步任务
4-5 串联多个操作任务
- promise的then()返回一个新的promise,可以开发then()的链式调用
- 通过then的 链式调用串联多个同步/异步任务
4-6 异常穿透
- 概念 :
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 前面任何操作出了异常,都会传到最后失败的回调中处理
- 中断promise链
- 当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数
- 方法 : 在回调函数中返回一个pendding状态的promise对象
4-7 中断Promise链
return new Promise(() => { });
五、 自定义手写Promise
手撸promise源码,请参考:
六、 async和await
6-1 async函数
函数的返回值为promise对象
promise对象的结果由async函数之心的返回值决定
<script> async function main() { // 如果返回值是一个非promise类型的数据 return 521; // 如果返回的是一个Promise对象 return new Promise((resolve, reject) => { resolve('OK'); // reject('Error') }) // 3. 抛出异常 throw "oh no"; } let result = main(); console.log(result); </script>
6-2 await 表达式
- await 右侧的表达式一般为promise对象,但也可以是其他的值
- 如果表达式是promise对象,await返回的是promise成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
6-3 注意
- await必须写在async函数中,但async函数中可以没有await
- 如果没有await的promise失败了,就会抛出异常,需要通过 try …catch捕获处理
边栏推荐
- TopoLVM: 基于LVM的Kubernetes本地持久化方案,容量感知,动态创建PV,轻松使用本地磁盘
- 学习太极创客 — MQTT 第二章(二)ESP8266 QoS 应用
- mmdetection ValueError: need at least one array to concatenate解决方案
- Pat grade a 1021 deep root
- Flink learning 4:flink technology stack
- 2021:passage retrieval for outside knowledgevisual question answering
- jmeter将上一个请求的结果作为下一个请求的参数
- Flink学习1:简介
- Learn Tai Chi maker mqtt (IX) esp8266 subscribe to and publish mqtt messages at the same time
- Learn Tai Chi Maker - mqtt Chapter 2 (3) reserved messages
猜你喜欢

Implementation of window encryption shell

2021:Greedy Gradient Ensemble for Robust Visual Question Answering

Il manque beaucoup de fichiers et de répertoires tels que scripts pendant et après l'installation d'anaconda3

Pat grade a 1021 deep root

I found a JSON visualization tool artifact. I love it!

Yiwen teaches you Kali information collection

发现一款 JSON 可视化工具神器,太爱了!

Uni app's uparse rich text parsing perfectly parses rich text!

resnet152 辣椒病虫害图像识别1.0

mmdetection 用yolox训练自己的coco数据集
随机推荐
Flink学习2:应用场景
Flink learning 3: data processing mode (stream batch)
PAT甲级 1019 General Palindromic Number
paddlepaddle 19 动态修改模型的最后一层
【微服务|Sentinel】降级规则|慢调用比例|异常比例|异常数
2016Analyzing the Behavior of Visual Question Answering Models
jmeter将上一个请求的结果作为下一个请求的参数
2022 Chinese pastry (Advanced) recurrent training question bank and online simulation test
[Shangshui Shuo series] day 6
TechSmith Camtasia latest 2022 detailed function explanation Download
学习太极创客 — MQTT 第二章(三)保留消息
Web development framework - Express (installation and use, static hosting, routing processing, use of Middleware)
TP5 spreadsheet excel table export
Flink学习1:简介
Pat grade a 1026 table tennis
jmeter分布式压测
Is the division of each capability domain of Dama, dcmm and other data management frameworks reasonable? Is there internal logic?
元透实盘周记20220627
2016Analyzing the Behavior of Visual Question Answering Models
2021:passage retrieval for outside knowledgevisual question answering