资讯专栏INFORMATION COLUMN

ES6中Generator

zhunjiee / 864人阅读

摘要:道理大概就是,有两个异步程序,用小明和小红指代它们。小红需要等小明执行完了才可以被执行,那么我们在执行到小明时,暂停程序的运行通过,等到小明有了返回结果时,再执行后面跟着的小红。在最新的中,已经抛弃了,转而使用。

ES6中Generator

Generator是ES6一个很有意思的特性,也是不容易理解的特性。不同于let/const提供了块级作用域这样明显的目的,这玩意儿被搞出来到底是干嘛的?

首先我们需要明确一个问题,在JavaScript中,任何一个函数只要开始执行,便无法停止下来直到执行完成(别跟我提debug,你见过哪个用户在使用产品的还得开个debug调试你的代码)。

but,Generator提供这种能力。 看下面代码:

function *g(){
    console.log("start");
    yield 1;
    console.log("middle");
    yield 2;
    console.log("end");
}
var g1 = g();
console.log(g1.next()); 
// start
// {value: 1, done: false}
console.log(g1.next());  
// middle
// {value: 2, done: false}
console.log(g1.next());  
// end
// {value: undefined, done: true}

根据输出结果,我们看到,在函数g中,碰到yield关键词,运行的程序会停下来。只有调用 next()方法,才会继续执行函数g中的代码。所以函数g本身有暂停状态

至此,我们需要知道:

Generator不是函数,不是函数,不是函数;

g()不会立即出发执行,而是一上来就暂停,并返回一个Iterator对象;

每次g1.next()都会打破暂停状态去执行,直到遇到下一个yield或者return

遇到yield时,会执行yeild后面的表达式,并返回执行之后的值,然后再次进入暂停状态,此时done: false。

遇到return时,会返回值,执行结束,即done: true

每次g.next()的返回值永远都是{value: ... , done: ...}的形式

Generator与异步

既然Generator可以函数停下来,有些脑洞清奇的人,想到了可不可以用Generator处理异步程序。

先看一个传统例子:

    function asyn(fn) {
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                fn();
                resolve(true);
            }, 1000);
        });
    }

    function main() {
        console.log("start");
        asyn(function(d) {
            console.log("async one");
            asyn(function(d) {
                console.log("async two");
                console.log("end");
            });
        });
    }

    main();

再来看看使用了Generator的异步程序:

    function asyn(fn) {
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                fn();
                resolve(true);
            }, 1000);
        });
    }

    co(function*() {
        console.log("start");
        yield asyn(function(d) {
            console.log("async one");
        });

        yield asyn(function(d) {
            console.log("async two");
        });
        console.log("end");
    });

    function co(fn) {

        return new Promise((resolve,reject)=>{
            let g = fn();

            onFullfilled();
            function onFullfilled() {
                let ret = null;
                ret = g.next();
                next(ret);
            }

            function next(ret) {
                if(ret.done) return resolve(ret.value);
                ret.value.then(onFullfilled);
            }
        } );
    }

函数在异步程序没有采用嵌套回调,是直接用同步的方式写了出来。道理大概就是,有两个异步程序,用小明和小红指代它们。小红需要等小明执行完了才可以被执行,那么我们在执行到小明时,暂停程序的运行(通过yield),等到小明有了返回结果时,再执行后面跟着的小红(next())。

在上面的程序中,我们添加了一个co函数,这个函数的作用是让Generator自动执行下去。直白来说,就是当第一个异步函数返回后,自动调用next()方法运行后面的代码。

Generator与Koa

Koa是基于Node.js的Web应用框架。在Koa中,处理的异步程序主要是网络请求(HTTP)、文件读取和数据查询。这里面的异步场景较多,如果再加上程序分层,采用传统的callback方式,那回调多了去了。

app.on("get", function(){
    auth(function(){
        router(function(){
            find(function(){
                save(function(){
                    render(function(){
                        //......
                    })
                })
            })
        })
    })

})

这样写法对于程序维护及其不利,毫无便捷性可言。在有了generator后,我们便可以像上面那种方式来写程序。Koa最初的版本就是通过这种方式,让中间处理程序都转成一个个"yield"(中间件)。通过中间件的形式去处理客户端请求,让开发App应用更加灵活,不受框架自身限制。

在最新的Koa2中,已经抛弃了Genetator,转而使用async/await

但是无论采用哪种方式,其本质都是利用了Promise。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98413.html

相关文章

  • ES6学习笔记之Generator函数

    摘要:调用函数后和普通函数不同的是,该函数并不立即执行,也不返回函数执行结果,而是返回一个指向内部状态的对象,也可以看作是一个遍历器对象。第一个只是用来启动函数内部的遍历器,传参也没有多大意义。 之前断断续续接触到了一些ES6的知识,异步编程方面听得比较多的就是Promise,直到最近比较系统地学习了ES6的新特性才发现Generator这个神奇的存在,它可以实现一些前所未有的事情,让我顿时...

    cjie 评论0 收藏0
  • 深入理解 Generator 函数

    摘要:同时,迭代器有一个方法来向函数中暂停处抛出一个错误,该错误依然可以通过函数内部的模块进行捕获处理。 本文翻译自:Diving Deeper With ES6 Generators 由于个人能力有限,翻译中难免有纰漏和错误,望不吝指正issue ES6 Generators:完整系列 The Basics Of ES6 Generators Diving Deeper With E...

    jzzlee 评论0 收藏0
  • 关于协程和 ES6 Generator

    摘要:关于协程和中的什么是协程进程和线程众所周知,进程和线程都是一个时间段的描述,是工作时间段的描述,不过是颗粒大小不同,进程是资源分配的最小单位,线程是调度的最小单位。子程序就是协程的一种特例。 关于协程和 ES6 中的 Generator 什么是协程? 进程和线程 众所周知,进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同,进程是 CPU 资源分配的最小单位,...

    RyanHoo 评论0 收藏0
  • 【Web全栈课程三】ES6特性介绍(下)

    摘要:示例运行函数弹出弹出函数接收参数,返回值。其中,返回一个对象,是的返回值,代表函数是否执行完成。 ES6特性介绍(下) ES6新的标准,新的语法特征:1、变量/赋值2、函数3、数组/json4、字符串5、面向对象6、Promise7、generator8、ES7:async/await 《【Web全栈课程二】ES6特性介绍(上)》见:https://segmentfault.com/a...

    wangshijun 评论0 收藏0
  • ES6 系列之 Babel 将 Generator 编译成了什么样子

    摘要:前言本文就是简单介绍下语法编译后的代码。如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎,对作者也是一种鼓励。 前言 本文就是简单介绍下 Generator 语法编译后的代码。 Generator function* helloWorldGenerator() { yield hello; yield world; return ending...

    EddieChan 评论0 收藏0

发表评论

0条评论

zhunjiee

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<