Promise 介绍与基本使用
- 1、 `Promise` 是什么?
- 2、创建 `Promise` 实例对象
- 3、Promise 实例方法
- 4、Promise 的基本工作流程
- 5、实例方法
- 6、静态方法
- 7、`async` 和 `await`
- 7.1、关键字
- 7.2、实例
- 7.3、区别
- 7.4、为什么使用 `async/await` 比较好?
1、 Promise
是什么?
-
所谓
Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 -
Promise
是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理和更强大。 -
Promise
对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。 -
Promise
对象提供统一的接口,使得控制异步操作更加容易。
2、创建 Promise
实例对象
- 简单抽奖实例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h2 class="page-head">Promise 初体验</h2>
<button type="button" class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
const btn = document.getElementById('btn')
btn.addEventListener('click', function () {
// Promise 形式实现
const p = new Promise((resole, reject) => {
// resole:解决,函数类型的参数 - 异步任务成功的时候调用
// reject:拒绝,函数类型的参数 - 异步任务失败的时候调用
// Promise 可以包裹一个异步任务
setTimeout(() => {
let n = Math.floor((Math.random() * 100) + 1)
if (n <= 30) {
// 成功 - 调用 resole 将 Promise 对象(p)的状态设置为 【成功】
resole(n)
} else {
// 失败 - 调用 reject 将 Promise 对象(p)的状态设置为 【失败】
reject(n)
}
}, 1000)
})
// 处理成功、失败的结果
// 调用 .then() 方法,传入两个函数类型的参数
.then((res) => {
// 成功时候调用
alert('恭喜你中奖了,奖品为:一台iphone 12 pro max!您的号码为:' + res)
}, (err) => {
// 失败时候调用
alert('再接再厉!您的号码为:' + err)
})
})
</script>
</body>
</html>
- 文件读取
const fs = require('fs')
// Promise 实现
function myReadFile(path) {
// 翻译个 Promise 对象
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', (err, data) => {
if (err) {
reject(err)
return
}
resolve(data)
})
})
}
myReadFile('./test2.txt').then(data => {
console.log('成功', data);
}, err => {
console.log('失败', err);
})
3、Promise 实例方法
.then()
// promise状态为fulfilled(已成功)
// 参数:函数,函数内部的参数是resolve传过来的实参
.catch()
// promise状态为rejected(已失败)
// 参数:函数,函数内部的参数是reject传过来的实参
.finally()
// 无论promise状态是成功还是失败,都会执行里面的代码
4、Promise 的基本工作流程
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
,它们是两个函数- 1、
resolve
作用是将promise
对象状态从未完成变为成功,异步操作成功时调用,并将异步操作的结果作为参数传出去。reject
作用是将promise
的状态从未完成变为失败,在异步操作失败时调用,并将异步操作报的错作为参数传递出去
- 2、
promise
对象代表一个异步操作有三个状态:pending
初始状态,fulfilled
操作成功,rejected
操作失败状态
- 3、
promise
的状态一经改变,只有两种可能:从pending
变为fulfilled
,从pending
变为rejected
状态发生改变之后就不会再变,会一直保持这个结果,这时就称为resolved
(已定型)
- 1、
5、实例方法
- 可以使用链式调用:因为这三个方法的返回值都是
promise
实例
.then()
// promise状态为fulfilled(已成功)
// 参数:函数,函数内部的参数是resolve传过来的实参
.catch()
// promise状态为rejected(已失败)
// 参数:函数,函数内部的参数是reject传过来的实参
.finally()
// 无论promise状态是成功还是失败,都会执行里面的代码
- 简单例子
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<script src="./test.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-head">Promise 初体验</h2>
<button type="button" class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script>
const btn = document.getElementById('btn')
btn.addEventListener('click', function () {
// Promise 形式实现
const p = new Promise((resole, reject) => {
// resole:解决,函数类型的参数 - 异步任务成功的时候调用
// reject:拒绝,函数类型的参数 - 异步任务失败的时候调用
// Promise 可以包裹一个异步任务
setTimeout(() => {
let n = Math.floor((Math.random() * 100) + 1)
if (n <= 30) {
// 成功 - 调用 resole 将 Promise 对象(p)的状态设置为 【成功】
resole(n)
} else {
// 失败 - 调用 reject 将 Promise 对象(p)的状态设置为 【失败】
reject(n)
}
}, 1000)
})
// 处理成功、失败的结果
// 调用 .then() 方法,传入两个函数类型的参数
.then((res) => {
// 成功时候调用
alert('恭喜你中奖了,奖品为:一台iphone 12 pro max!您的号码为:' + res)
})
.catch(err => {
// 失败时候调用
alert('很遗憾,您没有中奖,您的号码为:' + err)
})
.finally(() => {
// 无论成功、失败都会调用
alert('抽奖结束')
})
console.log(p);
})
</script>
</body>
</html>
6、静态方法
Promise.all([pro1,pro2])
// 将pro1和pro2包装成数组作为实参传递进去
// 返回值:promise对象。结果 =》pro1,pro2都成功才成功,有一个失败就失败
Promise.race([pro1,pro2])
// 将pro1和pro2包装成数组作为实参传递进去
// 返回值:promise对象。结果 =》pro1,pro2谁先回来就用谁都结果(无论成功或者失败)
Promise.any([pro1,pro2])
// 将pro1和pro2包装成数组作为实参传递进去
// 返回值:promise对象。结果 =》pro1,pro2都失败才失败,有一个成功就成功
Promise.resolve()
// 参数:任意
// 返回值:状态为fulfilled的promise对象
Promise.reject()
// 参数:任意
// 返回值:状态为rejected的promise对象
7、async
和 await
async
函数是generator
函数的语法糖,是ES6的异步编程解决方案async
await
是对promise
的优化,async
await
是一种更优雅的写法,将异步的代码优化为了同步的写法
7.1、关键字
function
关键字前加上async
(异步) 异步请求之前,加上await
(等待)
7.2、实例
async function findAll() {
let res = await $.get('......');
console.table(res.data)
}
7.3、区别
- 1、函数的前面多了一个
async
关键字。await
只能在async
中使用。await
是阻塞的意思,就是暂停,你一起调用2个接口,第一个执行完,不输出结果,要等最第二个接口执行完,才返回这两个的结果。 - 2、
async
生成的结果是promise
对象,async
是promise
的终结版。
7.4、为什么使用 async/await
比较好?
async
:async
是 ES7async
语法使得代码简洁清晰,不需要写那么多的箭头函数,避免了代码嵌套async
在接收上一个返回值为参数时,比较方便
Promise
:Promise
是 ES6Promise
主要用于异步任务,将异步的任务队列化,他主要解决了异步操作不小心就会进入回调地狱模式中,他将回调地狱的嵌套模式改为了链式调用模式,利于代码可读性和维护性。Promise
不能在返回表达式的箭头函数中设置断点。如果你在.then
代码块中设置断点,进入下一步的话,调试器不会跳到下一个.then
,因为他只会跳过异步代码。- 简单例子:
// 比如这样的场景,调用promise1,使用promise1的返回结果去调用promise2,然后使用两者的结果去调用promise3
const maskRequest = () =>{
return promise1().then(res1=>{
return promise2(res1).then(res2=>{
return promise3(res1,res2)
})
})
}
- 这样的操作会导致代码嵌套很多,不易与解读。
- 使用
async/await
的话代码就变得异常的简单和直观
const maskRrequest = async()=>{
const res1 = await promise1()
const res2 = await promoise2(res1)
return await promise( res1 , res2 )
}