迭代器,生成器(generator)和Promise的“微妙”关系

需要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()

原文地址:https://www.cnblogs.com/cherryvenus/p/9552528.html

时间: 2024-10-08 22:28:38

迭代器,生成器(generator)和Promise的“微妙”关系的相关文章

生成器generator和迭代器Iterator

一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2,3,4,5]可以使用list(range(6)),但是如果想要生成[,,,,,]即[0,1,4,9,16,25]怎么做? #方法一:循环>>> L = []>>> for x in range(6):... L.append(x**2)...>>> L[

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

前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 本文将详细介

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

generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,可以使用next()函数和send()函数恢复生成器. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用.但是,不同于一般函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这个消耗的内存数量将大大减小.因此,生成器看起来像是一个函数,但是表现得像迭代

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

python学习第十三天 迭代器 生成器

1.函数复习总结 # 函数 -- 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),**kwargs # 站在实参的角度上 : 按照位置传,按照关键字传 # 返回值:没有返回值 返回一个值 返回多个值 # 接收返回值:没有返回值不接收,返回一个值用一个变量接收,返回多个值用一个变量或者对应数目的变量接收 # 闭包函数 -- 在内部函数引用外部函数的变量 # 装饰器函

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

Python高级编程之生成器(Generator)与coroutine(一):Generator

这是一系列的文章,会从基础开始一步步的介绍Python中的Generator以及coroutine(协程)(主要是介绍coroutine),并且详细的讲述了Python中coroutine的各种高级用法,最后会用coroutine实现一个简单的多任务的操作系统. 其实也是看完这篇文章的学习笔记吧!O(∩_∩)O 生成器(Generator) 什么是生成器?在Python中,生成器(Generator)是一个带有yield关键字的函数 1 def gene(): 2 a = 1 3 print "

生成器generator

生成器generator 定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 代码: def cash_out(amount): while amount >0: amount -= 1 yield 1<br> print("擦,又来取钱了...败家子!") ATM = cash_out(5) print("取到钱 %s 万" % ATM.__next__())

Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func):    #定义装饰器     de