zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Generator函数

函数 Generator
2023-06-13 09:12:15 时间

概念

  1. Es6提供的解决异步编程的方案之一
  2. Generator函数是一个状态机,内部封装了不同状态的数据
  3. 用来生成遍历器对象
  4. 可暂停函数(惰性求值)

1.yield:暂停

2.next 启动

每次返回的是yield后的表达式结果

特点

1.function与函数名之间有一个*号

2.内部用yield表达式定义不同状态

3.generator函数返回的是指针对象 而不会执行函数内部逻辑

4.调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value:yield 后的表达式结果/undefind,done:}

5.再次调用next方法会从上一个yield处开始直到最后

6.yield语句返回结果通常为undefind,当调用next方法时传参内容会作为启动时yield语句的返回值

小试牛刀

function* myGenerator(){
        console.log('hello word')
        yield 'hello'

    }
    myGenerator()
    //

我们定义了一个generator函数,当调用该函数时,却什么也没有执行 这是因为generator函数返回的是指针对象(参照Iterator) 而不会执行函数内部逻辑

既然返回值是指针对象,那么我们可以直接调用next()

function* myGenerator(){
        console.log('hello word')
        yield 'hello'

    }
    
    var t = myGenerator()
    t.next()
    //hello word

Generator执行生成指针对象,当调用指针对象next,开始执行函数逻辑,当遇到yield语句后,当前函数会在yield处暂停,如果yield后面是个表达式则会被返回,如果是语句则会被执行,在返回{value:undifind}

function* myGenerator(){
        console.log('hello word')
        yield 'hello'

    }
    
    var t = myGenerator()
    console.log(t.next())
    //返回如下
    hello word
    {value: "hello", done: false}

//第二种
    console.log('hello word')
        yield console.log('test')

    }
    
    var t = myGenerator()
    //返回如下
    console.log(t.next()) 
  hello word
  test
 {value: undefined, done: false}
 
 //第三种
 function* myGenerator(){
        console.log('hello word')
        yield console.log('test')
        console.log('暂停后执行')
        yield "generator"

    }
    
    var t = myGenerator()//指针对象
    console.log(t.next())
    console.log(t.next())
    //返回如下
    hello word
    test
    {value: undefined, done: false}
    暂停后执行
    {value: "generator", done: false}

done:false表示函数内部状态为执行完毕,当执行完毕时返回true

function* myGenerator(){
        console.log('hello word')
        yield console.log('test')
        console.log('暂停后执行')
        yield "generator"
        return '返回的结果'

    }
    
    var t = myGenerator()
    console.log(t.next())
    console.log(t.next())
    console.log(t.next())
    //返回如下
     hello word
    {value: undefined, done: false}
    暂停后执行
    {value: ‘返回的结果’ done: true}

yield一般返回undefined,我们可以在下一个next执行时传入参数,这个参数可作为yield的返回值

function* myGenerator(){
        console.log('hello word')
        let res = yield 'hello'
        console.log(res)
        yield "generator"

    }
    
    var t = myGenerator()
    console.log(t.next())
    console.log(t.next('返回值'))
    //返回如下
    hello word
   {value: "hello", done: false}
   返回值
   {value: "generator", done: false}

示例

基于Generator的特性我们可以解决异步回调问题 如下先发送请求获取新闻,在根据新闻得到当前新闻的评论

function getNews(url){
    $.get(url,function(data){
            console.log(data)
            let url = 'http://localhost:3000'+data.commentUrl;
        })
}

function* sendXml(){
    yield getNews('http://localhost:3000/news?id=2') //获取新闻
    yield getNews(url) //获取评论
}
//获取遍历器对象
let SX = sendXml();
SX.next()//第一次调用next

第一次调用next时 指针指向第一个yield,进行请求发送操作获取新闻数据,我们在getNews中获取到新闻数据对应的评论url,因此此时请求已经发送成功

接下来我们要获取评论内容,因此我们又要进行next操作

function getNews(url){
    $.get(url,function(data){
            console.log(data)
                
                let url = 'http://localhost:3000'+data.commentUrl;
                
        })
}
function* sendXml(){
    yield getNews('http://localhost:3000/news?id=2') //获取新闻
        yield getNews(url) //获取评论
}
//获取遍历器对象
let SX = sendXml();
SX.next()//第一次调用next
SX.next()//第二次调用next

按理说第二次调用进行到第二个yield,此时进行评论获取操作,但是评论获取需要上一个请求得到的url,我们在外面调用next根本没有办法将url传递进去,

因此外面在getNews函数内部调用next,并进行参数传递 。

function getNews(url){
    $.get(url,function(data){
           console.log(data)
           let url = 'http://localhost:3000'+data.commentUrl;
           SX.next(url)//第二次调用next
        })
}
function* sendXml(){
    let url = yield getNews('http://localhost:3000/news?id=2') //获取新闻
    yield getNews(url) //获取评论
}
//获取遍历器对象
let SX = sendXml();
SX.next()//第一次调用next

我们第二个next传递的参数会作为第一个yield的返回值,然后在进行 yield getNews(url)此时评论获取成功