目录
1.生成器Generator
生成器主要用来解决异步操作的问题。是一个异步编程的解决方案,可以防止回调地狱(多层回调函数套在一起的情况)的发生。
<script>
// 生成器函数
// 关键字 yield 中断生成器
function* Gen() {
console.log('AAA');
yield '返回AAA';
console.log('bbb');
yield '返回bbb';
console.log('ccc');
yield '返回ccc';
}
let itertator = Gen()
console.log(itertator.next()); //返回一个对象Object
/* done : false
value: "返回AAA "*/
itertator.next();
itertator.next();
</script>
- 生成器区别于其他函数最关键的一项就是生成其中是有*号的,但是对*号的位置却没有限制,可以写在function后面也可以写在函数名前面。
- 生成器函数返回的结果是迭代器 (iterator)对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
- 生成器可以传参也可以不传参。
- 在生成器中 yield关键字有中断、暂停的作用,也可以将yield理解为是一个分隔符,每调用一次next方法,执行一段代码。 yield后面还可以跟一个值或表达式,调用next 方法可以得到
- next 方法可以传递实参,作为 yield 语句的返回值
<script> function* gen(arg) { console.log(111, arg); let a = yield 'aaa'; //此时虽然声明了变量a,但却没有将yield 'aaa'赋值给a, //因为系统认定yield 'aaa'的结果是undefined console.log(222, a); //这个a取到的数值是我们第二次调用next()方法传过来的实参,结果是bab let b = yield 'bbb'; console.log(333, b); yield 'ccc'; } let ittt = gen(444); console.log(ittt.next()); console.log(ittt.next('bab')); console.log(ittt.next('cbc')); </script>
2.解决回调地狱的三种方法
- 方法一:用生成器来解决
<script> function one() { setTimeout(function () { console.log('1'); console.log( iii.next()); }, 2000); }; function two() { setTimeout(function () { console.log('2'); console.log( iii.next()); }, 500); }; function three() { setTimeout(function () { console.log('3'); console.log( iii.next()); }, 1000); }; function* time() { // one(); yield one(); // two(); yield two(); // three(); yield three(); }; let iii = time(); iii.next(); </script>
- 方法二:Prominse对象中then方法来解决
<script> function one(res) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(111) }, 2000) }) } function two() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(222) }, 500) }) } function three() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(333) }, 1000) }) } // let p1 = one(); one().then((res) => { console.log(res); return two(); }).then( (res1) => { console.log(res1); return three(); } ).then((res2) => { console.log(res2); }) </script>
-
方法三:async await
<script> function one(str, time) { return new Promise((resolve, reject) => { // 异步代码 将来可以走ajax请求 文件的读写 setTimeout(() => { // console.log(str); resolve(str) }, time) }) } const fn = async () => { let res1 = await one('aaa', 2000); let res2 = await one('bbb', 500); let res3 = await one('ccc', 1000); console.log(res1, res2, res3); } fn(); </script>
3. Promise对象
3.1什么是Promise对象
Promise是一个原生对象,他本身就是一个构造函数 ,需要用new Promise(回调函数)来进行实例化,他的设计初衷是 让开发者更合理、更规范地用于处理异步操作。
这个对象和我们之前学习的对象不太一样,他的传参相对来说要复杂一些,Promise对象的参数就相当于一个函数。
let p=new Promise((resolve(成功函数),reject(失败函数))=>{})
3.2Promise对象解决异步地狱问题
Promise是异步编程的一种解决方案,相当于一个容器(放的程序是异步代码)它里面保存着某个未来才会结束的事件(比如ajax请求)从语法上说, Promise是一个对象,从它可以获取异步操作的消息。Promise提供统的API,各种异步操作都可以用同样的方法进行处理。
3.3Promise对象的三种状态和两个过程
Promise对象代表一个异步操作,有三种状态
三个状态(状态是不可逆):(1)等待状态:pending;(2)成功状态: fulfilled(resolve);(3)失败状态: rejected;
两个过程:从等待到成功;从等待到失败。
3.4Promise的then方法
then的第一个参数,就是是用于实现 resolve()方法; 第二个参数,就是用于实现 reject()方法.调用 resolve(); 相当于 执行then 是第一个函数。
<script>
let num = Math.floor(Math.random() * 10);
console.log(num);
let p1 = new Promise((resolve, reject) => {
// resolve是一个函数名,成功
// reject是一个函数名,失败
if (num > 5) {
resolve();
// resolve 为一个函数,当调用这个函数时promise的状态会从等待到成功
} else {
reject();
// reject也是一个函数 当调用这个函数时promise状态会从等待到失败
}
});
console.log(p1);
// then() Promise.prototype.then=
// then()方法中有两个参数,参数一:是回调函数 (resolve这个函数的实现)
// 参数二:是回调函数 (reject这个函数的实现)
p1.then(() => {
// 这个花括号里面写入的是resolve函数的代码
console.log('成功');
}, () => {
// 这个花括号里面写入的是reject函数的代码
console.log('失败');
})
</script>
3.5 Promise的catch和 finally方法
catch方法:当执行出错时执行,因为yhen方法的第二个参数可以省略,此时可以用catch方法来定义失败时执行的代码。如果then()方法和catch方法中都定义了失败的函数,那么那个方法编写在前面,那个方法先执行。
finally方法:不管出错还是成功,都会执行。
p1.then((res) => {
// res成功的值
//编写成功的代码
}).catch((err) => {
// err失败的值
//编写失败的代码
}).finally(() => {
console.log('成功与否都会执行finally方法');
})
3.6 Promise的链式调用
Promise 的链式调用就是将多个异步操作连接成一条链,确保它们按照顺序依次执行,并且能够处理每个步骤的结果,使得代码更加清晰和易于理解。我们可以通过Promise的链式调用来解决回调地狱的问题。
Promise的then方法返回一个新的Promise对象(不是原对象),通过这个特点我们可以进行编写 Promise的链式调用,在 Promise的链式调用最常用的就是then方法的链式调用。因为只有 Promise对象才可以使用then方法,所以我们得保证p1.then()的返回值是Promise对象,才能保证后续链式调用正常的执行。当p1.then()的返回值不同时执行效果也不一样,下面我们来看一下不同返回值的不同效果。
p1.then().then().then()中 p1.then()的返回值 | 执行效果 |
返回值为非promise或者函数没有返回值(默认是undefined) | 此时状态表示成功,则下一个then调用时只能执行成功的回调。返回值时return后面的值。 |
返回值为 promise对象 | 由内部的代码来决定成功与否。 |
直接抛出错误 | 下一个then调用执行失败的回调 |
3.7 Promise的类属性
(1)Promise.resolve(value):返回一个解析过的 Promise 对象,其状态和值由参数决定。
(2)Promise.reject(reason):返回一个拒绝过的 Promise 对象,其状态和拒因由参数决定。
(3)Promise.all(iterable):返回一个 Promise 对象,该对象在可迭代参数中所有的 promise 都已经解析或者参数中不包含 promise 时回调完成。将多个promise的实例包裹成一个实例,数组形势传入,遇到失败就直接调用失败,后续的操作不在关注。成功直接调用成功函数 ,返回一个数组。返回的数组和传入的promise的实例一样
(4)Promise.race(iterable):返回一个 Promise 对象,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。将多个promise得实例包裹为一个实例,数组形势传入,返回实例中结果最快的哪一个 , 不管失败还是成功的调用。