需要Promise源码版的朋友:传送链接

本文主要讲述(iterator)和生成器*/yield之间的联系和各自的用法,以及生成器的高配版本aysnc/await的使用。

大纲:

  • 迭代器(iterator)
  • 生成器 */yield
  • 异步版生成器 aysnc/await

迭代器(iterator)

先瞅瞅“迭代”,这个词是什么意思呢?每一次“过程”的重复,称之为迭代。不过迭代是会保留结果的,也就说每次都是以上一次迭代的结果为基准,开始下一次的迭代。举个例子,迭代这个词经常出现在产品开发之中,每个周期都会有产品的迭代开发,但是不可能每次都是从零开始做产品,肯定是基于上一版本的产品进行开发,也就是进行迭代。

从中我们可以整理出关于迭代的两个关键点:

  • 过程是重复的
  • 返回上一次的迭代结果

那么JS中的“迭代器”是个怎样的概念呢?

查看MDN中的概念:传送地址

个人观点:JS中的迭代器,就是一个数组对象,不断地调用next重复获取过程,然后每次都返回一个结果。等到没有东西可返回了,就终止。因此next的返回对象有两个属性donevaluedone表示是否结束了,value表示当前迭代的结果。当donetrue的时候,表示迭代已结束,这时候是没有返回结果的也就是没有value这个属性。

然而迭代器是有一系列的规范的:

查看MDN中的概念:传送地址

迭代器

  • 关于迭代器,就是我们上面讨论的next方法,返回donevaluedone: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的“微妙”关系的更多相关文章

  1. Python 生成器 (generator) & 迭代器 (iterator)

    python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...

  2. Python进阶内容(四)--- 迭代器(Iterator)与生成器(Generator)

    迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...

  3. 生成器generator和迭代器Iterator

    一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2 ...

  4. 迭代器 (Iterator) 和 生成器 (Generator)

    其他章节请看: es6 快速入门 系列 迭代器 (Iterator) 和 生成器 (Generator) 试图解决的问题 let colors = ['red', 'blue', 'green', ' ...

  5. ES6中的迭代器(Iterator)和生成器(Generator)

    前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...

  6. Python之生成器(generator)和迭代器(Iterator)

    generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用y ...

  7. TypeScript 迭代器(iterator)和生成器(generator)

    ⒈迭代器(iterator) 1.可迭代性 当一个对象实现了Symbol.iterator属性时,我们认为它是可迭代的. 一些内置的类型如 Array,Map,Set,String,Int32Arra ...

  8. js数组的内部实现,迭代器,生成器和内包

    js内部实现 在js以外的很多语言中,数组将会隐式占用一段连续的内存空间.这种隐式的内部实现,使得高效的内存使用及高速的元素方法称为可能,而 在javascript中,数组实体是一个对象,所以通常的实 ...

  9. python各种模块,迭代器,生成器

    从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名就是test) 包:用来从逻辑上组织模块的,本质就是一个目 ...

随机推荐

  1. libjpeg交叉编译

    下载libjpeg http://libjpeg.sourceforge.net/ 解压tar -zxf jpegsrc.v6b.tar.gz cd jpeg-6b cp /usr/bin/libto ...

  2. luogu1966 火柴排队

    题目大意 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为: $\sum_{i=1}^n(a_i-b_i) ...

  3. 【附论文】Facebook推面部识别软件 精准度高达97.25%

    论文下载链接:http://pan.baidu.com/s/1gd86HXp 以下转载自36kr. 认脸对于人来说不是什么难事,除非是韩国小姐才需要最强大脑.但是计算机做同样的事情就要困难得多了.不过 ...

  4. Java IO流中 File文件对象与Properties类(四)

    File类 用来将文件或目录封装成对象 方便对文件或目录信息进行处理 File对象可以作为参数传递给流进行操作 File类常用方法 创建 booleancreateNewFile():创建新文件,如果 ...

  5. 准确率,精确率,召回率,F-measure 之间的关系

    总结:(图上 R的计算的分母应该是 :40+10 )(笔误) 模型条件放宽,负类被误判为正类的可能性就变大(即FP变大)精确率和准确率会受影响(变小) 模型条件变严格,正类有可能被误判为负类(即FN变 ...

  6. 使用WinSXS进行系统盘瘦身Windows 7/2008/10/2012不断变大的C盘(Windows 更新清理)

    这是一款非常给力的国产良心小工具,用阿里云ECS的时候,一个C盘没多久就被坑爹的微软更新沉余文件塞满.此工具简单好用一下搞定! 操作系统: 所有 NT 6.X 内核的操作系统.比如 Windows V ...

  7. bzoj 1426: 收集邮票【期望dp】

    我太菜了,看的hzwer的blog才懂 大概是设f[i]表示已经拥有了i张邮票后期望还要买的邮票数,这个转移比较简单是f[i]=f[i]*(i/n)+f[i+1]*((n-i)/n)+1 然后设g[i ...

  8. P1606 [USACO07FEB]荷叶塘Lilypad Pond(最短路计数)

    P1606 [USACO07FEB]荷叶塘Lilypad Pond 题目描述 FJ has installed a beautiful pond for his cows' aesthetic enj ...

  9. extjs grid禁止表格头部使用鼠标拖拽改变宽度

    extjs6 经典版 表格头部使用鼠标拖动 禁止改变列的宽度 只需要给grid 设置属性enableColumnResize:false就可以啦 xtype:'grid', enableColumnR ...

  10. java HashMap和LinkedHashMap区别

    我们用的最多的是HashMap,在Map 中插入.删除和定位元素,HashMap 是最好的选择.但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好.如果需要输出的顺序和输入的相同,那么用 ...