Promise的使用
一、什么是Promise?
官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
- Promise是ES6一个非常好用的特性
- Promise是异步编程的一种解决方案
- Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值
二、语法
new Promise( function(resolve, reject) {...} /* executor */ );
参数
创建实例对象时需要传入一个有 resolve 和 reject 两个参数的executor函数 。Promise构造函数执行时立即调用executor函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
总结:
- 通过 new 关键字创建一个 Promise 实例的时候,需要传入一个函数,这里的函数就是上边的 executor
- executor 函数里边还有两个参数,这两个参数分别是 resolve 和 reject ,这两个参数的本质有是一个函数。
- resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败),Promise的状态见下:
三、Promise的状态
四、代码演示
4.1 Promise的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//什么情况下会用到Promise?
//一般情况下是有异步操作时,使用Promis对这个异步操作进行封装
//new -》 构造函数(1.保存一些状态信息 2.执行传入的函数)
//在执行传入的回调函数时,会传入两个参数,resolve,reject,本身又是函数
new Promise((resolve, reject) => {
//此处用来包裹异步请求,用setTimeout来模拟异步请求
setTimeout(() => {
// 成功的时候调用resolve
resolve('success message')
//失败的时候调用reject
reject('error message')
},1000)
}).then((success) => { //成功时调用该函数
console.log(success);
console.log(success);
console.log(success);
}).catch((error) => { //失败时调用该函数
console.log(error);
console.log(error);
console.log(error);
})
</script>
</body>
</html>
4.2 Promise的另一种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
new Promise((resolve,reject) => {
// 把setTimeout当做异步请求,此处进行包裹
setTimeout(() => {
//成功时调用该函数
resolve('success message')
//失败时调用该函数
reject('error message')
},1000)
// 在then处可以一次传入两个函数,成功时调用第一个函数,失败时调用第二个函数
}).then((success) => { //成功时调用该函数
console.log(success);
},(error) => { //失败时调用该函数
console.log(error);
})
</script>
</body>
</html>
4.3 Promise的链式调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// Promise里边的参数是一个函数 ——》 (resolve,reject)
// resolve,reject本身又是一个函数
// 链式编程
new Promise((resolve,reject) => {
//里面用来包裹异步请求,此处用setTimeout来代替异步请求
//第一次网络请求的代码
setTimeout(() => {
//成功时调用该函数
resolve()
},1000)
}).then(() => {//成功时调用该函数
//第一次拿到结果的处理代码
console.log('Hello Java');
console.log('Hello Java');
console.log('Hello Java');
return new Promise((resolve,reject) => {
//第二次网络请求的代码
setTimeout(() => {
resolve()
},1000)
})
}).then(() => {
//第二次拿到结果处理代码
console.log('Hello VueJs');
console.log('Hello VueJs');
console.log('Hello VueJs');
return new Promise((resolve,reject) => {
//第三次网络请求的代码
setTimeout(() => {
resolve()
},1000)
})
}).then(() =>{
//第三次拿到结果处理代码
console.log('Hello Python');
console.log('Hello Python');
console.log('Hello Python');
})
</script>
</body>
</html>
4.3 Promise的链式调用小案例
需求
网络请求:aaa -> 自己处理(10行)
处理:aaa111 -> 自己处理(10行)
处理:aaa111222 -> 自己处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// wrapped into
//网络请求:aaa -> 自己处理(10行)
//处理:aaa111 -> 自己处理(10行)
//处理:aaa111222 -> 自己处理
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
//2.对结果进行第一次的处理
return new Promise((resolve) => {
resolve(res + '111')
})
}).then(res => {
console.log(res, '第二层的10行处理代码');
//3.对结果进行第二次的处理
return new Promise((resolve) => {
resolve(res + '222')
})
}).then((res) => {
console.log(res, '第三层的10行处理代码');
})
上边代码的简写形式
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
//2.对结果进行第一次的处理
return Promise.resolve(res + '111')
}).then(res => {
console.log(res, '第二层的10行处理代码');
//3.对结果进行第二次的处理
return Promise.resolve(res + '222')
}).then((res) => {
console.log(res, '第三层的10行处理代码');
})
//对上边代码的另一种简写形式
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('aaa')
},1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
//2.对结果进行第一次的处理
return res + '111'
}).then(res => {
console.log(res, '第二层的10行处理代码');
//3.对结果进行第二次的处理
return res + '222'
}).then((res) => {
console.log(res, '第三层的10行处理代码');
})
</script>
</body>
</html>
五、Promise的all方法的使用
代码演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//需求:假设现在要做一个页面,必须同时向后台发送两次请求,并且当这两次请求都完成了,该页面才可以显示成功
//使用原始的ajax来实现
//定义两个变量用来记录请求完成的状态
let isResult1 = false
let isResult2 = false
// 请求一:
$ajax({
url:'url1',
success:function () {
console.log('结果1');
isResult1 = true
//并不能确定两次请求谁先完成,所以每次请求里边都需要调用处理最终结果的方法
handleResult()
}
})
// 请求二:
$ajax({
url:'url2',
success:function () {
console.log('结果1');
isResult2 = true
//并不能确定两次请求谁先完成,所以每次请求里边都需要调用处理最终结果的方法
handleResult()
}
})
// 定义一个函数用来处理最终的结果
function handleResult() {
if(isResult1 && isResult2){
//在这里处理最终结果
}
}
//上面的方法有点繁琐,可以用Promise里边的all方法来替代
//all里边传入的是一个数组
Promise.all([
//请求一:
new Promise((resolve,reject) => {
$ajax({
url:'url1',
success:function (data) {
resolve(data)
}
})
}),
//请求二:
new Promise((resolve,reject) => {
$ajax({
url:'url2',
success:function (data) {
resolve(data)
}
})
})
]).then((results) => { //此处的results是一个数组,把两次请求的结果都封装到一个数组里边了
console.log(results);
})
</script>
</body>
</html>