什么是迭代器?
迭代器是一种思想,一种设计模式
什么是迭代?
从一个数据集合中按照一定顺序,不断地取数据的过程
迭代和遍历的区别:
- 迭代可以不确定取出的值有多少,也可以不取完所有数据,强调的是过程。
- 遍历必须确定数据的长度,循环不断的全部取出,针对于数据量过大的情况下使用遍历,需要时间过长,强调的是结果。
数组的迭代:
let arr = [10, 20, 30]
//创建迭代器
let iter = arr[Symbol.iterator]() //可迭代对象都含有一个Symbol.iterator方法,返回一个迭代器
//迭代器都含有一个next方法
//value就是值,done表示迭代是否结束
console.log(iter.next()) // {value: 10, done: false}
console.log(iter.next()) // {value: 20, done: false}
console.log(iter.next()) // {value: 30, done: false}
console.log(iter.next()) // {value: undefined, done: true}
可迭代对象
可以用for..of
遍历的就是可迭代对象,可迭代对象可以创建出迭代器。
例如:数组、字符串、Map、dom元素…
注意:对象不是可迭代对象!!!
设计可迭代对象
我们可以自行把一个对象设计为可迭代对象:
为了让对象可迭代(也就让 for..of
可以运行)我们需要为对象添加一个名为 Symbol.iterator
的方法(一个专门用于使对象可迭代的内建 symbol)。
- 当
for..of
循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个 迭代器(iterator) —— 一个有next
方法的对象。 - 从此开始,
for..of
仅适用于这个被返回的对象。 - 当
for..of
循环希望取得下一个数值,它就调用这个对象的next()
方法。 next()
方法返回的结果的格式必须是{done: Boolean, value: any}
,当done=true
时,表示循环结束,否则value
是下一个值。
这是带有注释的完整实现:
let range = {
stus: ["小明", "小红", "小刚"],
//添加一个Symbol.iterator方法
[Symbol.iterator]() {
let index = 0; //对应的索引
const this_ = this;
//返回一个迭代器————一个有 next 方法的对象
return {
//next方法
next() {
//如果有元素返回元素值和done:false,否则返回{ value: undefined, done: true }
if (index < this_.stus.length) {
const ret = {
value: this_.stus[index], done: false };
index++;
return ret;
} else {
return {
value: undefined, done: true };
}
},
};
},
};
for (let num of range) {
alert(num); // 1, 然后是 2, 3, 4, 5
}
什么是生成器?
生成器是一种可以用来控制迭代器(iterator)的函数,它可以随时暂停,并可以在任意时候恢复。
生成器函数
写法:
function
与函数名之间有一个星号*
- 函数体内部有
yield
关键字
function * genFunc(){
yield 1;
yield 2;
yield 3;
}
生成器函数的执行机制
genFunc();
这并不是执行函数里面的代码,而是创建了一个迭代器
这是通过生成器来创建一个迭代器
let iter = genFunc();
iter.next();
调用next
才开始去执行生成器函数里面的代码,当执行碰到yiekd
时就会停下执行,并跳出这个函数,返回yield后面的值(加工成一个对象)给调用next
的地方
iter.next();
再次调用next
,再次进入到生成器函数里面执行代码,碰到yiekd
时又会停下执行,如此反复
总结:
- 通过调用生成器函数来创建迭代器(此时生成器函数不会执行)
- 通过迭代器调用
next
执行生成器函数里面的代码 - 执行到
yield
暂时跳出函数并把yiely
后面的值加工成对象返回到调用next
的地方
应用场景
第一个异步请求成功后再去发送第二个请求,第二个请求成功后再去发送第三个请求,每一个请求是基于前面一次请求成功后才来发送请求,因为要拿到上一次的数据
- 基于Promise的写法
function useApi(x){
return new Promise((resolve, reject) =>{
//模拟一秒后得到响应
setTimeout(() =>{
resolve(++x)
},1000)
})
}
useApi(0).then(result1 =>{
console.log('第一次请求结果为:${result1}');
return useApi(result1)
}).then(result2 =>{
console.log('第二次请求结果为:${result2}');
return useApi(result2)
}).then(result3 =>{
console.log('第三次请求结果为:${result3}');
return useApi(result3)
})
- 生成器创建迭代器的写法
function useApi(x){
return new Promise((resolve, reject) =>{
//模拟一秒后得到响应
setTimeout(() =>{
resolve(++x)
},1000)
})
}
function * genFunc(x){
let result1 = yield useApi(x)
console.log('第一次请求结果为:${result1}');
let result2 = yield useApi(result1)
console.log('第二次请求结果为:${result2}');
let result3 = yield useApi(result2)
console.log('第二次请求结果为:${result3}');
}
本文同步更新到我的博客,欢迎大家前来访问~
https://blog.zlpo.xyz/