Generator的异步实现

整理了一下在学习和使用JS异步过程中的一些知识点。核心是在Generator实例的的回调中调度实例的下一步,同样的思想也能用于其它语言。比如Python中使用Generator实现了协程。C#早期有也这种TheadPool+Generator的异步实现。

什么是Generator

Generator 为生成器的意思,生成器函数的执行可以分段执行,函数在每一次调用后,函数只会执行到下一个位置再跳出函数。

Generator的简单使用

通过在申明方法的时候使用 * 和方法内使用yield 来表明自己的生成器函数身份。而调用生成器函数返回一个生成器。

function * buildGen(){
let r = yield 1;
console.log(`get: ${r}`);
return 2;
}
const gen = buildGen();
//gen 就是一个Generator,可以通过next 函数不断向下调用;
var next = gen.next();
console.log(next);
//{done:false,value:1}
next = gen.next("hello");
//get: hello
console.log(next);
//{done:true,value:2}

如上所示,调用buildGen后并没有立即执行,需要通过next函数才能工作,调用next()后返回一个显示当前完成状态和返回值的对象。

我们也可以通过向next 函数传递参数,完成向生成器传递信息。

Generator实现异步

通过Generator可以将JS的多重回调写法,变成同步写法。使异步使用更加易于理解。

function * buildGen(){
yield timeOutLogAsync(1000);
yield timeOutLogAsync(2000);
//yield readFileAsync('./test.txt');
}
function timeOutLogAsync(millseconds){
return (callback)=>{
setTimeout(callback,millseconds);
}
}
const gen = buildGen();
gen.next().value(()=>{
console.log(`first setTimeout is called`);
gen.next().value(()=>{
console.log(`sencond setTimeout is called`);
//gen.next();
});
});

以上代码还有一个问题,就是在需要手动执行next的来执行下一步,并且嵌套回调的结构也不利于阅读。不过可以通过引入自运行函数来解决这个问题。

function run(generator){
const gen = generator();
//内部实现了一个逆归调用
function next(err,value){
if(err){
throw err;
}
let handler = gen.next(value);
if(handler.done){
return;
}
handler.value(next);
}
next();
}
run(buildGen);

Thunk函数

在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成单参数的版本,且只接受回调函数作为参数。

//正常函数
fs.readFile(fileName,callback); const readFileThunk = function(fileName){
return (callback)=>{
fs.readFile(fileName,callback);
}
}
//thunk函数
readFileThunk(fileName)(callback);

thunkify 模块

thunkify模块提供了封装好的Thunk函数转换器。

npm install thunkify

使用如下

const thunkify = require("thunkify");
const fs = require("fs");
const readFileThunk = thunkify(fs.readFile);
readFileThunk('./test.txt')(function(err,value){
//...
});

源码见github

根据源码,thunkify 只能针对如fs.readFile(...args[],callback)这样将callback作为最后一个参数的标准函数,如果想要使用像setTimeout(callback,time)这样的函数,则需要我们做一个转换,如:

const executeTimeout = (time,callback) => setTimeout(callback,time);
const executeTimeoutThunk = thunkify(executeTimeout);
executeTimeoutThunk(1000)(function(){
console.log(new Date()) ;
});

co 模块

co模块是个流程管理模块。基于ES6的Generator和yield,能让我们用同步的形式编写异步代码。提供了上文中的run函数的作用。

npm install co


co(function*(){
var file1 = yield readFileThunk('./test.txt',{encoding:'utf8'});
console.log(file1);
var file2 = yield readFileThunk('./test2.txt',{encoding:'utf8'});
console.log(file2);
});

JS中Generator的学习小记的更多相关文章

  1. JS中childNodes深入学习

    原文:JS中childNodes深入学习 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <ti ...

  2. js中关于prototype学习(2015年1月5号晚)

    prototype在js中为原型,只要是对象都有原型,最高原型为Object. 函数作为一特殊的对象,下面探讨prototype(原型)和function(函数)之间的关系. function A ( ...

  3. js中this指向学习总结

      在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象.一般在编译期绑定. 然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质 ...

  4. Js中Array数组学习总结

    第一次写博客...有点方... 小白一枚(是真的小白),自学前端,下面来说说我在学习过程中总结的一些数组操作,如果说哪有错误,请各位大神多多指出,小的虚心接受. 引用类型分为Object类型(所谓的对 ...

  5. js 中的yield

    yield是什么 yield是ES6的新关键字,使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者.它可以被认为是一个基于生成器的版本的return关键字. yield关键字实 ...

  6. js 正则学习小记之匹配字符串

    原文:js 正则学习小记之匹配字符串 今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高 ...

  7. js 正则学习小记之匹配字符串优化篇

    原文:js 正则学习小记之匹配字符串优化篇 昨天在<js 正则学习小记之匹配字符串>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯 ...

  8. js 正则学习小记之匹配字符串字面量优化篇

    昨天在<js 正则学习小记之匹配字符串字面量>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯后用 [^"] 才能匹配成功 ...

  9. JavaScript学习12 JS中定义对象的几种方式

    JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...

随机推荐

  1. 蓝桥杯——分组比赛(2017JavaB组第3题)

    分组比赛(17JavaB3) 9名运动员参加比赛,需要分3组进行预赛. 有哪些分组的方案呢? 标记运动员为 A,B,C,... I 下面的程序列出了所有的分组方法: ABC DEF GHI ABC D ...

  2. Network-Emulator-Toolkit 模拟各种网络环境 windows

    背景.目标.目的 (1) 背景: 我们在使用网络时,时常遇到在正常网络环境下的代码运行一切正常,可以复杂的网络环境下的各种问题无法复现,必须搭建模拟各种网络环境,去复现问题,定位问题.不管是移动平台, ...

  3. Spring与Web环境集成

    1. Spring与Web环境集成 1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(sprin ...

  4. jwt介绍

    jwt原理 最简单理解:jwt本质就是, 把用户信息通过加密后生成的一个字符串 JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户 { "UserName" ...

  5. 从0开始带你成为JVM实战高手(百度网盘)

    狸猫技术窝<从0开始带你成为JVM实战高手> 之前写过几篇 JVM 相关的文章,最近复盘的时候,发现狸猫技术窝<从0开始带你成为JVM实战高手>真的不错,然后就在网上找了一下( ...

  6. Python学习随笔:使用xlwings设置和操作excel多行多列数据以及设置数据字体颜色填充色对齐方式的方法

    ☞ ░ 前往老猿Python博文目录 ░ 在前面老猿的文章中,<Python学习随笔:使用xlwings读取和操作Excel文件>.<Python学习随笔:使用xlwings读取和操 ...

  7. PyQt(Python+Qt)学习随笔:containers容器部件GroupBox分组框介绍

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 1.主要属性 GroupBox分组框是一个对多个部件进行编组的框架容器,可以带有标题(title属性 ...

  8. 前端性能测试(H5性能测试)

    前端性能调优方法同样适用于H5. 1.H5前端性能知识点 学习前端性能,必须对HTTP协议有所了解. 1.1 浏览器渲染引擎 浏览器是Html解析和页面最终展示的工具. 浏览器的主要功能:将用户选择的 ...

  9. LeetCode初级算法之数组:1 两数之和

    两数之和 题目地址:https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整 ...

  10. CF1147F Zigzag Game & 稳定婚姻问题学习笔记

    CF1147F Zigzag Game 这题太神仙了,不得不记录一下. 我网络流做不动了,DS做不动了,DP做不动了,特别自闭.于是博弈论之神(就是随手切3500博弈的那种) \(\color{bla ...