迭代器,生成器(generator)和Promise的“微妙”关系
需要Promise源码版的朋友:传送链接
本文主要讲述(iterator)和生成器*/yield
之间的联系和各自的用法,以及生成器的高配版本aysnc/await
的使用。
大纲:
- 迭代器(iterator)
- 生成器
*/yield
- 异步版生成器
aysnc/await
迭代器(iterator)
先瞅瞅“迭代”,这个词是什么意思呢?每一次“过程”的重复,称之为迭代。不过迭代是会保留结果的,也就说每次都是以上一次迭代的结果为基准,开始下一次的迭代。举个例子,迭代这个词经常出现在产品开发之中,每个周期都会有产品的迭代开发,但是不可能每次都是从零开始做产品,肯定是基于上一版本的产品进行开发,也就是进行迭代。
从中我们可以整理出关于迭代的两个关键点:
- 过程是重复的
- 返回上一次的迭代结果
那么JS中的“迭代器”是个怎样的概念呢?
查看MDN中的概念:传送地址
个人观点:JS中的迭代器,就是一个数组对象,不断地调用
next
重复获取过程,然后每次都返回一个结果。等到没有东西可返回了,就终止。因此next
的返回对象有两个属性done
和value
。done
表示是否结束了,value
表示当前迭代的结果。当done
为true
的时候,表示迭代已结束,这时候是没有返回结果的也就是没有value
这个属性。
然而迭代器是有一系列的规范的:
查看MDN中的概念:传送地址
迭代器
- 关于迭代器,就是我们上面讨论的
next
方法,返回done
和value
(done:true
时可以省略)两个参数。
function iteratorFunc(){
let arr=[...arguments]
let nIndex=0
return {
next:()=>{
return nIndex<arr.length?
{value:arr[nIndex++],done:false}:{done:true}
}
}
}
let a=iteratorFunc(1,2,3)
console.log(a.next())//{done:false,value:1}
console.log(a.next())//{done:false,value:2}
console.log(a.next())//{done:false,value:3}
console.log(a.next())//{done:true}
可迭代“对象”
- 关于可迭代“对象”,我们需要再对象上实现
@@iterator
方法,也就是[Symbol.iterator]
,返回一个自定义的迭代方法,以表明这个对象是可以迭代的。有些JS内置的对象就是可迭代的,比如String,Array。
自带的可迭代事例:
let str="我是欢乐的迭代器"
let b=str[Symbol.iterator]()
console.log(b.next())//{value: "我", done: false}
console.log(b.next())//{value: "是", done: false}
console.log(b.next())//{value: "欢", done: false}
有没有很神奇啊!用了这么久的字符串,居然还有这种操作。他的效果等同于上方的自定义迭代方法。那么我们来写个自定义的迭代方法:
str[Symbol.iterator] = function() {
return { // this is the iterator object, returning a single element, the string "bye"
next: function() {
this._index += 2
if (this._index<str.length) {
return { value: str[this._index], done: false };
} else {
return { done: true };
}
},
_index:-2
};
};
let c=str[Symbol.iterator]()
console.log(c.next())//{value: "我", done: false}
console.log(c.next())//{value: "欢", done: false}
console.log(c.next())//{value: "的", done: false}
console.log(c.next())//{value: "代", done: false}
console.log(c.next())//{done: true}
这里我写的迭代器是返回一个隔一个字符。运行成功yeah
生成器(generator)
感觉写迭代器还是很绕呢,于是出现了生成器(generator),专门帮我们生成迭代器的存在。
function * g(){}
let it= g()
console.log(it.next())//{value: undefined, done: true}
看到熟悉的结构没有!{value: undefined, done: true}
,不过我们没有值。这个时候要向大家推荐*
的好基友yield
,一个yield
对应一个next
的值。
我们改写下上方的字符串的迭代器:
str[Symbol.iterator]= function * (){
let index=-2;
while(index<this.length){
index += 2
yield this[index]
}
}
let kk=str[Symbol.iterator]()
console.log(kk.next())//{value: "我", done: false}
console.log(kk.next())//{value: "欢", done: false}
console.log(kk.next())//{value: "的", done: false}
console.log(kk.next())//{value: "代", done: false}
是不是方便了很多。
我们带着几个疑问来看看生成器:
yield
的返回值是啥?- 执行顺序?
实例代码:
function * gy(){
console.log("zero")
let fisrt=yield "first"
console.log("fisrt",fisrt)
let second=yield "first"
console.log("second",second)
}
let ity= gy()
第一次执行ity.next()
,只打印了zero
第二次执行ity.next()
,只打印了first undefined
第三次执行ity.next("third")
,只打印了second third
由此可见每次的next都止步于yield
,就不再执行下去了。yield
每次返回的都是当前ity.next(value)
的value
值。
aysnc/await
我们来看看对于Promise这个对象的迭代器,我们该怎么处理。也就是每个迭代器都是异步的。
function setTime(value,id){
return new Promise((r,j)=>setTimeout(() => {
console.log(value)
r(id)
}, 10))
}
function *a(){
let r1 = yield setTime("first",1)
console.log(r1)
let r2 =yield setTime("second",2)
console.log(r2)
let r3 =yield setTime("third",3)
console.log(r3)
}
let k=a();
new Promise((resolve,reject)=>{
function next(data){
let {value,done}=k.next(data)
//k.next()返回一个promise,因此可以then
if(!done){
value.then((data)=>{
console.log(data)
next(data)
})
}
}
next();
})
因为每个都是异步的,所以需要我们二次处理,这个时候aysnc/await
就可以出场了。只需要把*/yield无缝改成aysnc/await即可。
async function a() {
let r1 = await setTime("first",1)
console.log(r1)
let r2 = await setTime("second",2)
console.log(r2)
let r3 = await setTime("third",3)
console.log(r3)
}
a()
迭代器,生成器(generator)和Promise的“微妙”关系的更多相关文章
- Python 生成器 (generator) & 迭代器 (iterator)
python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...
- Python进阶内容(四)--- 迭代器(Iterator)与生成器(Generator)
迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...
- 生成器generator和迭代器Iterator
一.列表生成式 在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2 ...
- 迭代器 (Iterator) 和 生成器 (Generator)
其他章节请看: es6 快速入门 系列 迭代器 (Iterator) 和 生成器 (Generator) 试图解决的问题 let colors = ['red', 'blue', 'green', ' ...
- ES6中的迭代器(Iterator)和生成器(Generator)
前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...
- Python之生成器(generator)和迭代器(Iterator)
generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用y ...
- TypeScript 迭代器(iterator)和生成器(generator)
⒈迭代器(iterator) 1.可迭代性 当一个对象实现了Symbol.iterator属性时,我们认为它是可迭代的. 一些内置的类型如 Array,Map,Set,String,Int32Arra ...
- js数组的内部实现,迭代器,生成器和内包
js内部实现 在js以外的很多语言中,数组将会隐式占用一段连续的内存空间.这种隐式的内部实现,使得高效的内存使用及高速的元素方法称为可能,而 在javascript中,数组实体是一个对象,所以通常的实 ...
- python各种模块,迭代器,生成器
从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名就是test) 包:用来从逻辑上组织模块的,本质就是一个目 ...
随机推荐
- linux启动基本流程
linux启动序列 1.CPU初始化 CPU自身初始化.从某个固定位置(0xfffffff0)取指令并运行,该指令为跳转指令.跳转到BIOS代码的首部. 2.装载BIOS BIOS被固化在 ...
- location.replace
[root@bigdata-server-01 ~]# curl www.baidu.com<!DOCTYPE html><!--STATUS OK--><html> ...
- delphi中URL的汉字编码
delphi中URL的汉字编码 show.asp?sort=全部&sortlevel=1&gorq=供&n=5&sitename=全部&img=yes& ...
- YTU 2508: 武功秘籍
2508: 武功秘籍 时间限制: 1 Sec 内存限制: 128 MB 提交: 1384 解决: 438 题目描述 小明到X山洞探险,捡到一本有破损的武功秘籍(2000多页!当然是伪造的). 他 ...
- android 制作9.png图片
什么叫.9.PNG呢,这是安卓开发里面的一种特殊的图片 这种格式的图片在android 环境下具有自适应调节大小的能力. (1)允许开发人员定义可扩展区域,当需要延伸图片以填充比图片本身更大区 ...
- CodeForces 446A DZY Loves Sequences (DP+暴力)
题意:给定一个序列,让你找出一个最长的序列,使得最多改其中的一个数,使其变成严格上升序列. 析:f[i] 表示以 i 结尾的最长上升长度,g[i] 表示以 i 为开始的最长上升长度,这两个很容易就求得 ...
- /usr/lib64/python2.6/lib-dynload/pyexpat.so: symbol XML_SetHashSalt, version EXPAT_2_0_1_RH not defined in file libexpat.so.1 with link time reference
解决方法:[root]$cd /usr/lib64/python2.6/lib-dynload[root]$ln -s /lib64/libexpat.so.1.5.2 libexpat.so.0[r ...
- cookie使用详解
cookie是用来保存客户资料的好方法,与同样可以用来保存客户资料的 session不同的是,session是把资料保存在服务器端,而cookie是把资料保存在客户端,我们平常接触的最多的cookie ...
- Asp.NET 知识点总结(二)
1.两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 答:不对,有相同的 hash code 编码格式. 2.swtich是否能作用在byte ...
- Rabin_Karp(hash) HDOJ 1711 Number Sequence
题目传送门 /* Rabin_Karp:虽说用KMP更好,但是RK算法好理解.简单说一下RK算法的原理:首先把模式串的哈希值算出来, 在文本串里不断更新模式串的长度的哈希值,若相等,则找到了,否则整个 ...