一、Generator
是ES6提供的一种异步编程解决方案,语法不同于普通函数;简单的把Generator 理解为一个状态机,封装了多个内部状态。执行Generator 函数会返回一个迭代器对象,可以通过调用迭代器next依次遍历Generator函数内部的每一个状态。
(一)Gererator函数的特征:
1.function关键字和函数名之间有*号(可以紧跟function,也可以紧跟函数名,也可以在两者之间)
2.函数内部使用yield表达式
普通的函数
function test(){
//想要Generato函数有返回值
3行代码
return 1
3行代码
return 2
3行代码
return 3
3行代码
return 4
Generator函数
function* test(){
//想要Generato函数有返回值
//Generator状态机管理
3行代码
yield 1
3行代码
yield 2
3行代码
yield 3
3行代码
yield 4
}
在普通函数中只要有return之后,后面的代码将不再执行,而Generator函数中提供了yield,每调用一次next()就执行一个yeild的状态,上一个yeild的结束是下一个yeild的开始。最后一个yeild可以换成return。
(二)Generator函数的创建
Generator函数返回的是一个可迭代对象, 调用next()方法会执行yiled的状态,一个yield就是一个状态 一个yield就是一个代码的节点。
<body>
<!-- Generator函数返回一个迭代器对象 next()方法 会执行yiled的状态
一个Yield就是一个状态 一个yield就是一个代码节点
-->
<script>
function* Generator () {
// 内部使用yield表达式(不会像return一样阻止代码向下执行)
yield '1我是第一个返回值状态 我被执行了'
yield '2'
yield '3'
}
let res = Generator() //返回值返回的是一个迭代器对象或者generator对象
// console.log(res);
for (let k of res) {
console.log(k);
}
console.log(res);
console.log(res.next());//调用一次next执行一个状态
// console.log(res.next());//调用一次next执行一个状态
// console.log(res.next());//调用一次next执行一个状态
</script>
</body>
(三)模拟发起异步请求,拿第一个状态的返回结果再执行第二个状态 状态之间的数据传递通过next()
<script>
function* Generator () {
// 内部使用yield表达式
log();
let res = yield '1';
// 返回值 对这个状态耳朵描述
// 如果想要在第二个状态使用第一个状态的返回值
// 直接使用是获取不到的
console.log(res, '获取res');
log();
yield '2'
log();
yield '3'
}
let res = Generator()
// 返回值 返回的是一个迭代器对象/generation对象
res.next();//发起第一个状态的执行
res.next(100);
// 如果想要在第二个状态拿到第一个状态的返回值
// 就需要在第二个状态执行的时候传递参数
// 发起第二个状态的执行
// 模拟异步请求
function log () {
for (let i = 1; i <= 10; i++) {
console.log(i);
}
}
</script>
<script>
function* Generator () {
let res = yield getData();
console.log(res, '获取响应');
yield '结束了'
}
let res = Generator()//返回值 返回的是一个迭代器对象/generator对象
res.next();
async function getData () {
// 发起一个异步请求
let result = await axios.get('https//....');
// 应该在第一个状态的异步请求中发起第二段程序/第二个状态的执行
// 上一个状态返回值作为下一个状态的入口
// 第一个状态的方法里面发起第二个状态的执行
res.next(result);
}
</script>
二、Promise
是一种异步编程解决方案,Promise是一个容器,保存着将来才会执行的代码;从语法角度来说Promise是一个对象,可以用来获取异步操作的消息。异步操作,同步解决,避免了层层嵌套的回调函数,可以链式调用降低了操作难度 .
1.实例化
Promise构造函数接收一个函数作为参数,也就是回调函数;该函数的两个参数分别是resolve和reject。resolve作为成功的回调函数,reject作为失败的回调函数。Promise对象代表一个异步操作有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。最后返回resolved(已定型)结果。
2.实例方法
定义在Promise.prototype中的方法,通过Promise实例可以直接调用
then(res=>{}) 状态由pending变为fulfilled的时候也就是异步操作成功之后执行该回调函数
参数:回调函数,回调函数的参数为resolve函数传递过来的值
返回值:返回一个新的Promise实例对象,因此可以使用链式调用
catch(err=>{}) 由pending变为rejected的时候执行该回调函数也就是异步失败之后执行该回调函数
参数:回调函数,回调函数的参数为reject函数传递过来的值
返回值:返回一个新的Promise实例对象,因此可以使用链式调用
finally()无论异步操作执行成功失败与否,都会执行该回调
参数:回调函数
返回值:返回一个新的Promise实例对象
<script>
// 声明一个promise对象
// Promise函数:参数 回调函数(resolve,reject)
let promise = new Promise((resolve, reject) => {
// resolve代表的是成功回调函数
// reject 代表的是失败回调函数
// 模拟异步请求
if (3 > 2) {
resolve('success')
} else {
reject('error')
}
})
console.log(promise, '承诺对象');
// resolve reject由谁提供
// resolve由then方法提供 reject由catch提供
// then可以有两个参数
// promise.then(res=>{
// console.log(res,'请求成功');
// },err=>{
// console.log(err,'请求失败');
// })
promise.then(
// 执行的是成功的回调函数
(res) => {
console.log(res, '请求成功');
}
).catch(
// 执行的是失败的回调函数
(err) => {
console.log(err, '请求失败');
}
).finally(() => {
console.log('最终执行');
})
// finally loading
// 这个项目 数据一直不回来 loading=false
// Promise 做什么? 封装AJAX
</script>
3.静态方法:只能由构造函数本身去调用
定义在Promise方法中,通过Promise可以直接调用
<body>
<script>
// 创建多个承诺对象得实例
// let p1=new Promise(()=>{
// // 发异步请求
// 四步走
// resolve();//请求成功
// reject();//请求失败
// })
function promise (method, url, obj) {
return new Promise((reslove, reject) => {
// 封装ajax
let xhr = new XMLHttpRequest();
// 打开一个连接
xhr.open(method, url);
// 发送请求
xhr.send();
// 接收响应
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 代表请求成功
reslove(xhr.responseText)
} else {
// 代表请求失败
reject(xhr.responseText)
}
}
}
})
}
let p1 = promise('get', 'http://121.199.0.35:8887/index/carousel/findAll');
let p2 = promise('get', 'http://121.199.0.35:8888/index/article/findCategoryArticles');
// 静态方法 只能由构造函数本身去调用 Promise
// 实例全部成功返回一个承诺对象
// 参数 数组[存放多个promise实例对象]
// 返回值 返回一个promise实例
// let res=Promise.all([p1,p2]);
// 任意一个实例状态成功返回成功得实例
// let res=Promise.any([p1,p2]);
// race 赛跑 返回请求先成功得实例对象
// let res=Promise.race([p1,p2]);
// let res = Promise.allSettled([p1, p2]);
// 区别?
// 1.返回得处理格式问题 array:[{},{}]
// all 实例 pendding
// console.log(res);
// res.then(res => {
// console.log(res);
// })
// console.log(res);
// res.then(res => {
// console.log(res, '请求成功');
// })
// console.log(p1, p2);
p1.then(res => {
console.log(res, '获取响应1');
});
// p2.then(res => {
// console.log(res, '获取响应2');
// });
</script>
</body>
Promise.all([p1,p2])
参数:数组,数组中的元素为Promise实例
返回值:Promise实例,当p1 p2都请求成功之后该实例的状态才是fulfilled,此时p1和p2的返回值
组成一个数组,传递给该实例的回调函数,只要p1,p2的返回值有一个变为rejected,该实例状态为rejected;
Promise.race([p1,p2])赛跑返回先请求成功的实例
参数:数组 数组中的元素为Promise实例
返回值:哪个先请求到就返回哪个请求的结果
Promise.any([p1,p2])
参数:数组 数组中的元素为Promise实例
返回值:Promise实例,只要p1,p2状态有一个变为fulfilled,该实例的状态为fulfilled;p1,p2状态都变为erjected,该实例状态才为rejected
Promise.allSettled([p1, p2])
参数:数组 数组中的元素为Promise实例
返回值:不管请求有没有成功此方法都会对这两个实例进行操作,但最终展示的是请求成功的数据