js 迭代器 生成器 异步代码处理 promise+生成器 -> await/async

一、迭代器

迭代器本身就是一个对象,可以帮助我们遍历另外一个对象在这里插入图片描述

1、认识迭代器
// 下面是我们编写的一个迭代器,就是一个对象。帮我们遍历容器结构
// const iterator = {
//   next: function () {
//     return {
//       done: true,
//       value: 123,
//     };
//   },
// };

// 数组
const names = ["a", "b", "c"];
const iterator = names[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// 控制台依次打印:
// { value: 'a', done: false }
// { value: 'b', done: false }
// { value: 'c', done: false }
// { value: undefined, done: true }

console.log("================================");
// 创建一个迭代器对象来访问数组
let index = 0;
const namesIterator = {
  next: function () {
    // return { done: false, value: "a" };
    // return { done: false, value: "b" };
    // return { done: false, value: "c" };
    if (index < names.length) {
      return { done: false, value: names[index++] };
    } else {
      return { done: true, value: undefined };
    }
  },
};
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
2 、迭代器函数
const names = ["a", "b", "c"];
const num = [10, 20, 30];

function createArrayIterator(arr) {
  let index = 0;
  return {
    next: function () {
      if (index < arr.length) {
        return {
          done: false,
          value: arr[index++],
        };
      } else {
        return { done: true, value: undefined };
      }
    },
  };
}
const namesIterator = createArrayIterator(names);
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());

const numIterator = createArrayIterator(num);
console.log(numIterator.next());
console.log(numIterator.next());
console.log(numIterator.next());
console.log(numIterator.next());
3、可迭代对象

在这里插入图片描述

for-of就是迭代器本质啦

// const names = ["a", "b", "c"];
// // 创建一个迭代器对象来访问数组
// let index = 0;
// const namesIterator = {
//   next: function () {
//     if (index < names.length) {
//       return { done: false, value: names[index++] };
//     } else {
//       return { done: true, value: undefined };
//     }
//   },
// };

// 可迭代对象
const iteratorObj = {
  names: ["a", "b", "c"],
  // 满足可迭代协议
  [Symbol.iterator]: function () {
    let index = 0;
    return {
      // 这里需要改成箭头函数
      next: () => {
        if (index < this.names.length) {
          return { done: false, value: this.names[index++] };
        } else {
          return { done: true, value: undefined };
        }
      },
    };
  },
};
console.log(iteratorObj[Symbol.iterator]);

// 1.第一次调用iteratorObj[Symbol.iterator]
const iterator = iteratorObj[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

// 第二次调用iteratorObj[Symbol.iterator]: 生成新的迭代器
const iterator1 = iteratorObj[Symbol.iterator]();
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());
console.log(iterator1.next());

// 3.for...of 可以遍历的东西必须是一个可迭代对象
// for其实是语法糖,做的就是iterator.next(),拿到对象,然后在取.value。当done:false,就把value取出来。done为true的时候,就停止遍历
const obj = {
  name: "chen",
  age: 23,
};
for (const item of obj) {
  console.log(item); //TypeError: obj is not iterable
}
4、原生迭代器对象

String、Array、Map、Set、arguments对象、NodeList集合都是, 注意:对象就不是了

// 内置创建可迭代对象
// 1、数组
const names = ["a", "b", "c"];
console.log(names[Symbol.iterator]);

const iterator = names[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

// 2、Map / Set
const set = new Set();
set.add(10);
set.add(100);
set.add(1000);
console.log(set[Symbol.iterator]().next());

for (const item of set) {
  console.log(item)
}

console.log('-----------')
// 3、函数中arguments也是一个可迭代对象
function foo(x, y, z) {
  for (const arg of arguments) {
    console.log(arg)
  }
}
foo(10, 20, 30)
5、可迭代器对象的应用场景
// 1、for-of
// 2、展开运算符

const names = ["a", "b", "c"];
const obj = {
  name: 'chen',
  age: 23
}
// 不可以迭代
// for (const item of obj) {
//   console.log(item)
// }

// 值得注意的是,下面这样是可以的
// 这是ES9中新增的一个特性,专门针对对象展开做的特殊处理,用的也不是迭代器。通过obj.entries()
const newObj = { ...obj }
console.log(newObj) //{ name: 'chen', age: 23 }
// 这种也不是使用迭代器,使用的还是entries()
const { name, age } = obj

// 3、解构语法,使用的还是迭代器,调的是next().value
const [name1, name2, name3] = names
console.log(name1, name2, name3) // a b c

// 4、创建一些对象时
const set1 = new Set(names)
// const set2 = new Set(1334); //报错
// 创建数组
const arr1 = Array.from(names)

// 5、Promise.all
Promise.all(names).then(res => {
  console.log(res) //[ 'a', 'b', 'c' ]
})
6、自定义类的可迭代性
// class Person {

// }

// // 不是可迭代对象
// const p1 = new Person();
// const p2 = new Person();

// 案例: 创建一个教师类,创建出来的对象都是可迭代对象
class Classroom {
  constructor(address, name, students) {
    this.address = address;
    this.name = name;
    this.students = students;
  }
  entry(newStudent) {
    this.students.push(newStudent);
  }
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.students.length) {
          return { done: false, value: this.students[index++] };
        } else {
          return { done: true, value: undefined }
        }
      }
    }
  }
}
const classroom = new Classroom('北京', '计算机教室', ['zhangsan', 'lisi', 'wangwu']);
classroom.entry('jianren')

// classroom不是可迭代的对象,如果想迭代,需要在类中加上[Symbol.iterator]
for (const item of classroom) {
  console.log(item)
}
// 下面输出:
// zhangsan
// lisi
// wangwu
// jianren

// 如果是function,也是一样的
// function Person () {

// }
// Person.prototype[Symbol.iterator] = function(){

// }

二、生成器

1、什么是生成器 - 生成器函数

在这里插入图片描述

// 生成器函数, 有* ,通过yield控制代码执行流程,返回值就是一个迭代器
function* foo() {
  console.log('函数开始执行~')

  // 代码执行的时候暂停
  // 第一段代码
  const value = 100
  console.log(value)
  yield

   // 第二段代码
  const value1 = 200
  console.log(value1)
  yield

   // 第三段代码
  const value2 = 300
  console.log(value2)
  yield

  console.log('函数执行结束!')
}

// 这么调用,一行代码不会执行
foo()

// 当我们调用生成器函数时,会返回一个生成器(特殊的迭代器)
const generator = foo()
// 执行第一段代码
generator.next()
// 执行第二段代码
generator.next()
// 执行第三段代码
generator.next()
2、生成器函数的执行流程
// 当遇到yield的时候只暂停函数的执行
// 当遇到return的时候,生成器就停止执行
function* foo() {
  console.log('函数开始执行~')

  const value = 100
  console.log(value)
  // return value,停止了。如果想返回,直接跟在后面
  yield value * 200

  const value1 = 200
  console.log(value1)
  yield

  const value2 = 300
  console.log(value2)
  yield

  console.log('函数执行结束!')
}

foo()

const generator = foo()
// generator.next()//100
// generator.next()//200
// generator.next()//300
// generator.next()

console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
// 依次打印:
// { value: undefined, done: true }
// { value: undefined, done: true }
// { value: undefined, done: true }
// { value: undefined, done: true }


// 返回的就是迭代器:
// 100
// { value: undefined, done: false }     
// 200
// { value: undefined, done: false }     
// 300
// { value: undefined, done: false }     
// 函数执行结束!
// { value: undefined, done: true } 
3、生成器的next传递参数
function* foo() {
  console.log('函数开始执行~')

  const value = 100
  console.log(value)
  const n = yield value

  const value1 = n * 10
  console.log(value1)
  yield

  const value2 = 300
  console.log(value2)
  yield

  console.log('函数执行结束!')
}

foo()


// 1. 生成器上的next方法可以传递参数
const generator = foo()
console.log(generator.next())
console.log(generator.next(10))
console.log(generator.next())
console.log(generator.next())
4、生成器替代迭代器的使用1
// 生成器替代迭代器
function* createArrayIterator(arr) {
  let index = 0;

  // 写法一:
  // yield arr[index++]; //{ done: true, value: undefined };
  // yield arr[index++];
  // yield arr[index++];
  
  // 写法二:
  // yield 'a'; 
  // yield 'b'; 
  // yield 'c'; 

  // 写法三:
  // for (const item of arr) {
  //   yield item;
  // }

  // 写法四: yield* 可迭代对象
  yield* arr

  // return {
  //   next: function () {
  //     if (index < arr.length) {
  //       return {
  //         done: false,
  //         value: arr[index++],
  //       };
  //     } else {
  //       return { done: true, value: undefined };
  //     }
  //   },
  // };
}

const names = ["a", "b", "c"]
const namesIterator = createArrayIterator(names);
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
console.log(namesIterator.next());
5、生成器替代迭代器的使用2
// 生成器替代迭代器
function* createArrayIterator(arr) {
  let index = 0;
  yield* arr;
}

// 2.创建一个函数,这个函数可以迭代一个范围内的数字
// 10 20
// function createRangeIterator(start, end) {
//   // 写法一:
//   let index = start;
//   return {
//     next: function () {
//       if (index < end) {
//         return {
//           done: false,
//           value: index++,
//         };
//       } else {
//         return { done: true, value: undefined };
//       }
//     },
//   };
// }

function* createRangeIterator(start, end) {
  // 写法一:
  let index = start;
  while (index < end) {
    yield index++;
  }
}


const iterator = createRangeIterator(10, 20);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

// 输出如下:
// { done: false, value: 10 }
// { done: false, value: 11 }
// { done: false, value: 12 }
// { done: false, value: 13 }
6、异步代码的处理方案
function requestData(url) {
  // 异步请求的代码会被放入到executor中
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(url);
    }, 1000);
  });
}

// 1.第一种方案: 多次回调
// 回调地狱
// requestData('chen').then(res => {
//   requestData(res + '/aaaa').then(res => {
//     requestData(res + '/bbbb').then(res => {
//       console.log(res);
//     })
//   })
// })

// 2.第二种方案: Promise中then的返回值来解决
// requestData('chen').then(res => {
//   return requestData(res + '/aaaa')
// }).then(res => {
//  return requestData(res + '/bbbb');
// }).then((res) => {
//   console.log(res);
// })

// 3.第三种方案: Promise + generator实现(手动执行)
// function* getData() {
//   const res1 = yield requestData("chen");
//   const res2 = yield requestData(res1 + "/aaaa");
//   const res3 = yield requestData(res2 + "/bbbb");
//   console.log(res3);
// }

// const generator = getData();
// generator.next().value.then((res) => {
//   // console.log(res); //如果想要拿到这个res,需要执行下一次next(),并把值传回去
//   generator.next(res).value.then((res) => {
//     // console.log(res);
//     generator.next(res).value.then((res) => {
//       console.log(res);
//     });
//   });
// });

// 3.第三种方案: Promise + generator实现(自动执行)
// function execGenerator(getFn) {
//   const generator = getFn();
//   // 使用递归
//   function exec(res) {
//     const result = generator.next(res);
//     if (result.done) {
//       return result.value;
//     } else {
//       result.value.then(res => {
//         exec(res);
//       })
//     }
//   }
//   exec();
// }
// execGenerator(getData);


// 4.第四种方案: await/async
// function* getData() {
//   const res1 = yield requestData("chen");
//   const res2 = yield requestData(res1 + "/aaaa");
//   const res3 = yield requestData(res2 + "/bbbb");
//   console.log(res3);
// }
// 其实是yield的语法糖
async function getData() {
  const res1 = await requestData("chen");
  const res2 = await requestData(res1 + "/aaaa");
  const res3 = await requestData(res2 + "/bbbb");
  console.log(res3);
}
getData()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值