文章目录
前言
此为学习笔记整理,具体参考b站尚硅谷学习视频。
一、Promise 的理解和使用
1、Promise 是什么?
(1)理解
①抽象表达:
- Promise 是一门新的技术(ES6 规范)
- Promise 是 JS 中进行异步编程的新解决方案(旧方案是单纯使用回调函数)
②具体表达:
1)它通过引入一个回调,避免更多的回调,简单说Promise就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果。
2) 从语法上来说: Promise 是一个构造函数
3) 从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值
那么,我们在学习中一般会遇到哪些异步编程问题呢:
①fs 文件操作
require('fs').readFile('./index.html', (err,data)=>{
})
②数据库操作
③AJAX
$.get('/server', (data)=>{
})
④定时器
setTimeout(()=>{
}, 2000);
(2)promise 的状态改变
Promise的状态其实就是实例对象中的一个属性【PromiseState】,有三种可能值pending未决定的、resolved(fullfilled)成功、rejected失败
①pending 变为 resolved
②pending 变为 rejected
说明: 只有这 2 种, 且一个 promise 对象只能改变一次
,无论变为成功还是失败, 都会有一个结果数据,成功的结果数据一般称为 value
, 失败的结果数据一般称为 reason
。
(3)Promise对象的值
实例对象中的另一个属性【PromiseResult】,保存着异步任务【成功/失败】的结果。
只有resolve与reject这两个函数才可以修改这个值
(4)promise 的基本流程
注意:
Promise 状态发生改变,就会触发.then()里的响应函数处理后续步骤.。
Promise 状态一经改变,不会再变。
Promise实例一经创建,执行器立即执行。
(5)promise 的基本使用
①基本编码流程
<script>
// 1) 创建 promise 对象(pending 状态), 指定执行器函数
const p = new Promise((resolve, reject) => {
// 2) 在执行器函数中启动异步任务
setTimeout(() => {
const time = Date.now()
// 3) 根据结果做不同处理
// 3.1) 如果成功了, 调用 resolve(), 指定成功的 value, 变为 resolved 状 态
if (time%2===1) {
resolve('成功的值 '+ time)
} else {
// 3.2) 如果失败了, 调用 reject(), 指定失败的 reason, 变为rejected 状态
reject('失败的值' + time)
}
}, 2000)
})
// 4) 能 promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
p.then(
value => {
// 成功的回调函数 onResolved, 得到成功的 vlaue
console.log('成功的 value: ', value)
},
reason => {
// 失败的回调函数 onRejected, 得到失败的 reason
console.log('失败的 reason: ', reason)
}
)
</script>
②使用 promise 封装基于定时器的异步
<script>
function doDelay(time) {
// 1. 创建 promise 对象
return new Promise((resolve, reject) => {
// 2. 启动异步任务
console.log('启动异步任务')
setTimeout(() => {
console.log('延迟任务开始执行...')
const time = Date.now() // 假设: 时间为奇数代表成功, 为偶数代表失败
if (time %2=== 1) {
// 成功了
// 3. 1. 如果成功了, 调用 resolve()并传入成功的 value
resolve('成功的数据 ' + time)
} else {
// 失败了
// 3.2. 如果失败了, 调用 reject()并传入失败的 reason
reject('失败的数据 ' + time) }
}, time)
})
}
const promise = doDelay(2000)
promise.then(
value => {
console.log('成功的 value: ', value)
},
reason => {
console.log('失败的 reason: ', reason)
},
)
</script>
③使用 promise 封装 ajax 异步请求
<script>
/*
可复用的发 ajax 请求的函数: xhr + promise
*/
function promiseAjax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState!==4) return
const {
status, response} = xhr
// 请求成功, 调用 resolve(value)
if (status>=200 && status<300) {
resolve(JSON.parse(response))
} else {
// 请求失败, 调用 reject(reason)
reject(new Error('请求失败: status: ' + status))
}
}
xhr.open("GET", url)
xhr.send()
})
}
promiseAjax('https://api.apiopen.top2/getJoke?page=1&count=2&type=video')
.then(
data => {
console.log('显示成功数据', data)
},
error => {
alert(error.message)
}
)
</script>
④案例1-promise初体验
现在我们有如下要求,用户点击抽奖按钮后,两秒之后显示是否中奖(30%概率),若中奖则弹出“恭喜恭喜,奖品为小熊笔记本一个,您的中奖数字为?”,若未中奖,则弹出“再接再厉,您的号码为?”。
<!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>抽奖</title>
</head>
<body>
<div class="container">
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
//生成随机数
function rand(m,n){
return Math.ceil(Math.random() * (n-m+1)) + m-1
}
//获取元素对象
const btn = document.querySelector('#btn')
//绑定单击事件
btn.addEventListener('click',()=>{
//普通方法
//定时器
// setTimeout(()=>{
// //30%中奖率,即可以获取1-100的一个随机数,如果小于等于30,则中奖
// let n = rand(1,100);
// //判断
// if(n<=30){
// alert('恭喜恭喜,奖品为小熊笔记本一个')
// }else{
// alert('再接再厉')
// }
// },2000)
//Promise形式实现
const p = new Promise((resolve,reject)=>{
//定时器
setTimeout(()=>{
//30%中奖率,即可以获取1-100的一个随机数,如果小于等于30,则中奖
let n = rand(1,100);
//判断
if(n<=30){
resolve(n);//将promise对象的状态设置为【成功】
}else{
reject(n