博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6中Generator
阅读量:5163 次
发布时间:2019-06-13

本文共 3123 字,大约阅读时间需要 10 分钟。

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.cnblogs.com/lalalagq/p/9906606.html

你可能感兴趣的文章
【c语言】求1~1000的阶乘和数
查看>>
Linux系统中imp导入dmp文件
查看>>
MongoDB 之 Limit 选取 Skip 跳过 Sort 排序 MongoDB
查看>>
rsyslogd 日志服务
查看>>
有权图的Floyed
查看>>
【swift学习笔记】四.swift使用Alamofire和swiftyJson
查看>>
jq选择器 第一部分
查看>>
android开发--(SimpleAdapter)运用
查看>>
tomcat的server.xml中的Context节配置
查看>>
iOS 中控件的appearance 属性的应用
查看>>
MTV电子相册: 照片转视频,电子相册制作软件
查看>>
使用localhost连接不上,使用127.0.0.1可以连上的解决方法和原因
查看>>
Python将多个excel表格合并为一个表格
查看>>
第二次代码评审
查看>>
有点沉重的步伐...
查看>>
MVVM大比拼之AngularJS源码精析
查看>>
高质量C++/C编程指南(附录:C++/C试题的答案)
查看>>
(转)字符串表达式求值(C#)
查看>>
设计模式学习笔记-组合模式
查看>>
IdentityServer4 学习笔记[1]-客户端授权
查看>>