V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
wjx0912
V2EX  ›  JavaScript

请教一段 js 生成器的代码

  •  
  •   wjx0912 · 2021-12-28 20:01:20 +08:00 · 2120 次点击
    这是一个创建于 1095 天前的主题,其中的信息可能已经有所发展或是发生改变。

    function ajax(url, callback) { console.log('ajax enter: ', url) // 1 、创建 XMLHttpRequest 对象 var xmlhttp if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest() } else { // 兼容早期浏览器 xmlhttp = new ActiveXObject('Microsoft.XMLHTTP') } // 2 、发送请求 xmlhttp.open('GET', url, true) xmlhttp.send() // 3 、服务端响应 xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { var obj = JSON.parse(xmlhttp.responseText) // console.log(obj) callback(obj) } } console.log('ajax leave: ', url) }

    function request(url) { console.log('request enter, url: ', url) ajax(url, res => { console.log('callback enter, url: ', url) getData.next(res) console.log('callback leave, url: ', url) }) console.log('request leave, url: ', url) }

    function* gen() { let res1 = yield request('http://www.httpbin.org/get?q=test1') console.log('res1: ', res1) let res2 = yield request('http://www.httpbin.org/get?q=test2') console.log('res2: ', res2) let res3 = yield request('http://www.httpbin.org/get?q=test3') console.log('res3: ', res3) } let getData = gen() getData.next()

    问题就是,为什么可以顺序执行?

    yield 后面一般跟一个值,但是这里是个函数,request 没有返回值也就是返回了 undefined , 为什么可以等待后台的 ajax 执行完呢?

    刚学到生成器,可能比较基础吧。希望不吝指导。

    8 条回复    2021-12-30 11:14:05 +08:00
    wjx0912
        1
    wjx0912  
    OP
       2021-12-28 20:03:57 +08:00
    lisianthus
        2
    lisianthus  
       2021-12-28 20:27:00 +08:00
    res 的值是通过 next 传过来的 ,代码的第 28 行
    Zhuzhuchenyan
        4
    Zhuzhuchenyan  
       2021-12-28 20:29:36 +08:00
    简单来说,
    let result = yield func()
    此时 result 的值和 func 的返回值没有丝毫关系,你如果在看书的话可以接着往下看,yield 的作用只是暂停当前生成器的运行然后等待下一次的 next 调用,并把下一次 next 调用传递的参数传递给 result ,你可以参考一下下面的例子

    function doSomething() {
    setTimeout(() => {
    gen.next("result")
    },0)
    }

    function* generatorFunction() {
    const result = yield doSomething()
    console.log(result)
    }

    var gen = generatorFunction()
    gen.next()
    wjx0912
        5
    wjx0912  
    OP
       2021-12-28 20:52:55 +08:00
    @lisianthus 谢谢。资料很不错
    wjx0912
        6
    wjx0912  
    OP
       2021-12-28 20:55:43 +08:00
    @Zhuzhuchenyan
    再请教下,按您上面的例子:

    function doSomething() {
    return "abc"
    }

    这里面没有 next ,相当于 const result = yield "abc"
    这种情况下就是不需要 next 了,对吧?
    rodrick
        7
    rodrick  
       2021-12-29 13:46:19 +08:00
    生成器相关有兴趣可以读一下 <你不知道的 js>中卷 写的比较清晰 你不要想的太复杂 let a = yield xxxx , yield 的作用就是在一次 next()调用后 到这里停止 把 yield 后面的东西执行(函数就执行 基础变量类型就返回) 然后等待下一次 next(aa)调用的试试 把 aa 塞到 yield 的位置 这里就是把 aa 赋值给了 a 你代码里就是 getData.next(res)的 res 赋值给 res1 这样 然后继续往下走 直到 done:true 为止
    "equest 没有返回值也就是返回了 undefined , 为什么可以等待后台的 ajax 执行完呢?" 能等待是因为你再 ajax 执行完了才调用了 next
    wjx0912
        8
    wjx0912  
    OP
       2021-12-30 11:14:05 +08:00
    @rodrick
    谢谢 书买了~~~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1243 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:55 · PVG 01:55 · LAX 09:55 · JFK 12:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.