Promise教程

1、promise简介

定义:promise是es6引入的一种新的解决异步编程的方案。从语法上来说,是一个构造函数,可以实例化对象,封装异步操作,获取成功或失败的结果,其优点是支持链式调用,可以解决回调问题;指定回调的方式更为灵活。

2、promise初体验

2.1 题目:设计一个抽奖,中奖的概率为30%

1):用常规方式实现

<!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>
		<button>点我抽奖</button>
	</body>
	<script>
		// 获取随机整数[min,max]
		function getRandom(min, max) {
			return Math.floor(Math.random() * (max - min + 1)) + min;
		}
		var btn = document.querySelector("button");
		btn.onclick = function () {
			setTimeout(() => {
				var n = getRandom(1, 100);
				if (n <= 30) {
					alert("恭喜您,获得一台全新iPhone15!");
				} else {
					alert("很遗憾,奖品与您擦肩而过,再接再厉!");
				}
			}, 3000);
		};
	</script>
</html>

2)promise实现:promise对象可以包裹一个异步操作,成功时调用resolve()方法,失败时调用reject方法,通过promise的then方法执行回调(第一个函数为成功时的回调,第二个为失败时的回调)

<script>
		// 获取随机整数[min,max]
		function getRandom(min, max) {
			return Math.floor(Math.random() * (max - min + 1)) + min;
		}
		var btn = document.querySelector("button");
		btn.onclick = function () {
			// setTimeout(() => {
			// 	var n = getRandom(1, 100);
			// 	if (n <= 30) {
			// 		alert("恭喜您,获得一台全新iPhone15!");
			// 	} else {
			// 		alert("很遗憾,奖品与您擦肩而过,再接再厉!");
			// 	}
			// }, 3000);
			var p = new Promise((resolve,reject)=>{
				setTimeout(() => {
					var n = getRandom(1, 100);
					if (n <= 30) {
						resolve() //将promise对象的状态设置为[success]
					} else {
						reject() //将promise对象的状态设置为[fail]
					}
				}, 3000);
			})
			// 调用then方法
			p.then(()=>{
				alert("恭喜您,获得一台全新iPhone15!");
			},()=>{
				alert("很遗憾,奖品与您擦肩而过,再接再厉!");
			})
		};
</script>

2.2 题目:封装一个函数sendAjax发送GET AJAX请求;参数URL;返回结果Promise对象

ajax.html

<!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>
		<button>发送sendAjax请求</button>
	</body>
	<script>
		// 封装一个sendAjax函数
		function sendAajx(url){
				return new Promise((resolve,reject)=>{
					var xhr = new XMLHttpRequest()
					// xhr.responseType = 'json'
					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(xhr.status)
							}
						}
					}
				})
			}
		var btn = document.querySelector("button");
		btn.onclick = function () {
			sendAajx('http://127.0.0.1:8000/ajax').then(
				(res)=>{
					console.log(res)
			},(code)=>{
				console.log('失败:'+code)
			})
		};
	</script>
</html>

server.js

const express = require('express')
var app = new express()
app.get('/ajax',(request,response)=>{
  response.setHeader('Access-Control-Allow-Origin','*')
  response.send("用户数据")
})
app.listen(8000,()=>{
  console.log('8000端口正在运行中....')
})

控制台打印结果:
在这里插入图片描述

3、promise的状态

  • promise的一个属性 [PromiseState]

    • pending 未决定的
    • resolved/fullfilled 成功的
    • rejected 失败的
  • promise状态的改变

    • pending–>resolved/fullfilled
    • pending–>rejected
const p=new Promise((resolve,reject)=>{})

在这里插入图片描述

4、promise对象的值

属性值 [PromiseResult],保存着异步任务成功或者失败后的结果,可以通过resolve和reject两个函数进行修改,即resolve或者reject的形参值
在这里插入图片描述

5、promise的工作流程

在这里插入图片描述

6、promise的相关API

(1)Promise构造函数:Promise(excutor){}

  • executor函数:执行器(resolve,reject)=> { }
  • resolve函数:内部定义成功时调用的函数:value => {}
  • reject函数:内部定义失败时调用的函数:reason=> {}

注意:excutor会在Promise内部立即同步调用,异步操作在执行器中执行

(2)Promise.prototype.then(onResolved,onRejected)

  • onResolved:成功的回调函数
  • onRejected:失败的回调函数
  • 最终返回一个新的Promise对象

(3) Promise.prototype.catch(onRejected)

  • onRejected:失败的回调函数
    在这里插入图片描述

    以下是promise函数对象中的方法,而非实例对象

(4)promise.resolve()方法:(value)=>{}

  • value:成功的数据或promise对象
  • 说明:返回一个成功或失败的promise对象
  • ①如果resolve传入的是一个非promise的值,返回值为成功的promise,其结果为该值,②如果传入的是一个promise对象,返回值成功或失败根据传入的promise决定,结果为传入的promise结果
let p1=Promise.resolve(520)
 console.log(p1);

 let p2=Promise.resolve(new Promise((resolve,reject)=>{
  resolve("ok")
 }))
 console.log(p2);
 
 let p3=Promise.resolve(new Promise((resolve,reject)=>{
  reject("err")
 }))
 console.log(p3);

在这里插入图片描述

(5)promise.reject()方法:(reason)=>{}

  • 说明:返回一个失败的promise对象(状态为rejected),传入什么,失败的结果就是什么,假如传入的是一个成功的promise对象,那么结果就是那个成功的promise对象
const p4=Promise.reject(new Promise((resolve,reject)=>{
  resolve("ok")
 }))
 console.log(p4);

在这里插入图片描述
(6)promise.all方法:[promise]=>{}

  • promise:包含n个promise数组
  • 说明:返回一个新的promise,只有所有promise都成功才成功,只要有一个失败都失败。如果成功,结果值为他们分别成功的结果组成的数组,如果失败,结果值为失败的那个promise的结果
let p1=new Promise((resolve)=>{
  resolve("ok")
 })
 let p2=new Promise((resolve)=>{
  resolve("success")
 })

 const p=Promise.all([p1,p2])

 console.log(p);

在这里插入图片描述

let p1=new Promise((resolve)=>{
  resolve("ok")
 })
 let p2=new Promise((resolve)=>{
  resolve("success")
 })
 let p3=new Promise((resolve,reject)=>{
  reject("err")
 })

 const p=Promise.all([p1,p2,p3])

 console.log(p);

在这里插入图片描述
(7) promise.race()方法:[promise]=>{}

  • promise:包含n个promise数组
  • 返回一个新的promise,第一个改变状态的promise为最终结果
let p1=new Promise((resolve)=>{
  setTimeout(()=>{
    resolve("ok")
  },1000)
  
 })
 let p2=new Promise((resolve)=>{
  resolve("success")
 })
 let p3=new Promise((resolve,reject)=>{
  reject("err")
 })

 const p=Promise.race([p1,p2,p3])

 console.log(p);

在这里插入图片描述

7、promise的几个关键问题

7.1 Promise对象状态改变的方式

  1. resolve函数
  2. reject函数
  3. throw抛出错误

相关代码:

<script>
  let p = new Promise((resolve,reject)=>{
    // 1、resolve函数
    resolve('ok') //pending => fullfiled(resolved)
    // 2、reject函数
    reject('error') // pending => rejected
    // 3、抛出错误
    throw '出问题了'
  })
   console.log(p)
</script>

打印结果分别为:
resolve():在这里插入图片描述
reject():
在这里插入图片描述
throw:
在这里插入图片描述

7.2 promise执行多个回调

当promise改变为对应状态时都会执行
相关代码:

 <script>
    let p = new Promise((resolve,reject)=>{
      resolve()
    })
    p.then(()=>{
      console.log('one');
    })
    p.then(()=>{
      console.log('two');
    })
  </script>

打印结果:

在这里插入图片描述

7.3 改变promise状态和指定回调谁先执行

1)都有可能,正常情况下,先指定回调,再改变状态,但也可以先改变状态再执行回调
2)如何先改变状态再指定回调?
① 在执行器中直接调用resolve()/reject
② 延长更长时间再调用then
3)什么时候才能得到数据?
① 如果先指定的回调,当状态改变时,回调函数就会调用,执行回调,得到数据
②如果先改变状态,当指定回调时,回调函数就会调用,得到数据

7.4 promise.then方法的返回结果特点

  1. 非promise,返回promise状态为成功,结果为返回的结果
  2. 为promise对象,返回的结果为promise的结果
  3. 抛出错误

相关代码:

<script>
  let p = new Promise((resolve,reject)=>{
    resolve()
  })
  let result = p.then(()=>{
    // 1.非promise,返回promise状态为成功,结果为返回的结果
    // return 'ok'
    // 2.为promise对象,返回的结果为promise的结果、
    // return new promise((resolve,reject)=>{
    //   reject('error')
    // })
    // 3.抛出错误
    throw '出了问题'
  },()=>{

  })
  console.log(result)
</script>

对于上述代码的打印结果分别如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.5 如何串联多个任务

练习代码:

<script>
  var p = new Promise((resolve,reject)=>{
    resolve('success')
  })
  p.then((val)=>{
    console.log(val)
    return 'ok'
  }).then((val)=>{
    console.log(val);
    return new Promise((resolve,reject)=>{
      resolve('yes')
    })
  }).then((val)=>{
    console.log(val);
  }).then((val)=>{
    console.log(val);
  })
</script>

打印结果如下:
在这里插入图片描述

7.6 异常传递穿透

1)当使用promise的then链式调用时,可以在最后指定失败的回调
2)前面任何一步操作出现异常,都会传到最后的失败中处理
相关代码:

<script>
  let p = new Promise((resolve,reject)=>{
    resolve()
  })
  p.then(()=>{
    console.log('err');
    reject()
  }).then(()=>{
    console.log('ok');
  }).catch(()=>{
    console.log('似乎出错了')
  })
</script>

打印结果:
在这里插入图片描述

7.7 如何中断promise链

1)当使用promise的·then链式调用时,在中间中断,不再调用后面的回调函数
2)方法:在回调函数中返回一个pending状态的promise对象
相关代码:

<script>
  let p = new Promise((resolve,reject)=>{
    resolve()
  })
  p.then(()=>{
    console.log(111);
    return new Promise(()=>{})
  }).then(()=>{
    console.log(222);
  }).then(()=>{
    console.log(333);
  })
</script>

打印结果:
在这里插入图片描述

8、async与await

8.1 MDN文档

async教程

8.2 Async函数

1)函数的返回结果为promise对象
2)promise对象的结果由async函数执行的返回值决定,与then类似

<script>
  async function main(){
    // 1.非promise,返回promise状态为成功,结果为返回的结果
    // return 'ok'
    // 2.为promise对象,返回的结果为promise的结果、
    return new Promise((resolve,reject)=>{
      reject('error')
    })
    // 3.抛出错误
    // throw '出了问题' 
  }
  let result = main()
  console.log(result);
</script>

8.3 await表达式

1)awat 右侧的表达式一般为promise对象,但也可以是其他的值
2)如果表达式是promise对象,awai返回的是promise成功的值
3)如果表达式是其他值,直接将此值作为await的返回值

注意:
①await必须写在async函数中,但async函数中可以没有await
②如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理

<script>
  async function main(){
    let p = new Promise((resolve,reject)=>{
      resolve('ok')
    })
    let p1 = new Promise((resolve,reject)=>{
      reject("Error")
    })
    let res1 = await p
    let res2 = await 'success'
    console.log(res1);
    console.log(res2);
    try{
      let res3 = await p1
    }catch (e){
      console.log(e)
    }
  }
  main()
</script>

打印结果:
在这里插入图片描述

完结,撒花!!!!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小姜鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值