ES6第十九章Generator函数异步应用

气象数据收集 国家气象信息中心-中国气象数据网 (cma.cn)国家气象信息中心-中国气象数据网 (cma.cn)预报数据:需要定制,收费10万+路面数据同化系统,实时。 阅读详情

为什么使用Generator?

如果依次读取两个以上的文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为"回调函数地狱"(callback hell)。

Generator的执行情况

function* gen(x) {
  var y = yield x + 2;
  return y;
}

var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

next方法的作用是分阶段执行Generator函数。每次调用next方法,会返回一个对象,表示当前阶段的信息(value属性和done属性)。value属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。

Generator信息交换

假如把上面最后一行代码中传入参数2,这个参数可以传入 Generator 函数,作为上个阶段异步任务的返回结果,被函数体内的变量y接收。因此,这一步的value属性,返回的就是2(变量y的值)。

g.next(2) // { value: 2, done: true }

Generator处理错误

Generator 函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。

function* gen(x){
  try {
    var y = yield x + 2;
  } catch (e){
    console.log(e);
  }
  return y;
}

var g = gen(1);
g.next();
g.throw('出错了');
// 出错了

Thunk函数(把传入方法fn的几个参数分成几个方法返回)

// ES5版本
var Thunk = function(fn){
  return function (){
    var args = Array.prototype.slice.call(arguments);
    return function (callback){
      args.push(callback);
      return fn.apply(this, args);
    }
  };
};

// ES6版本
const Thunk = function(fn) {
  return function (...args) {
    return function (callback) {
      return fn.call(this, ...args, callback);
    }
  };
};
var readFileThunk = Thunk(fs.readFile);
readFileThunk(fileA)(callback);

生产环境使用(thunkify)模块代替以上操作

Thunk函数的作用

从形式上将函数的执行部分和回调部分分开,这样我们就可以在一个地方执行函数,在另一个地方执行回调函数。

var fs = require('fs');
var readFile = thunkify(fs.readFile);

/*执行函数部分*/
var f1 = readFile('./a.js');

/*回调函数部分*/
f1(function(err,data1){
   //doSomething
})

应用:自动化执行Generator(采用递归避免回调嵌套)(‘co’模块)

function run(fn) {
  var gen = fn();

  function next(err, data) {
    var result = gen.next(data);
    if (result.done) return;
    result.value(next);
  }

  next();
}

function* g() {
  // ...
}

run(g);

有了这个执行器,执行 Generator 函数方便多了。不管内部有多少个异步操作,直接把 Generator 函数传入run函数即可。**当然,前提是每一个异步操作,都要是 Thunk 函数,**也就是说,跟在yield命令后面的必须是 Thunk 函数。

var g = function* (){
  var f1 = yield readFileThunk('fileA');
  var f2 = yield readFileThunk('fileB');
  // ...
  var fn = yield readFileThunk('fileN');
};

run(g);

`

利用co模块替换上面run 方法

co函数返回一个Promise对象,因此可以用then方法添加回调函数。

co(gen).then(function (){
  console.log('Generator 函数执行完成');
});

上面代码中,等到 Generator 函数执行结束,就会输出一行提示。

基于 Promise 对象的自动执行

首先,把fs模块的readFile方法包装成一个 Promise 对象。

var fs = require('fs');

var readFile = function (fileName){
  return new Promise(function (resolve, reject){
    fs.readFile(fileName, function(error, data){
      if (error) return reject(error);
      resolve(data);
    });
  });
};

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

然后,手动执行上面的 Generator 函数。

var g = gen();

g.next().value.then(function(data){
  g.next(data).value.then(function(data){
    g.next(data);
  });
});

手动执行其实就是用then方法,层层添加回调函数。理解了这一点,就可以写出一个自动执行器。

function run(gen){
  var g = gen();

  function next(data){
    var result = g.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }

  next();
}

run(gen);

co可以处理并发

co(function* () {
  var values = [n1, n2, n3];
  yield values.map(somethingAsync);
});

function* somethingAsync(x) {
  // do something async
  return y
}

上面的代码允许并发三个somethingAsync异步操作,等到它们全部完成,才会进行下一步。

深入解析经典蓝牙连接:从HCI命令到LMP协议的完整流程 本文深入解析经典蓝牙连接的完整流程,从设备发现、寻呼建立物理链路,到安全配对与加密的每一步。通过对照HCI LOG与AIR LOG,详细拆解了HCI命令与LMP协议报文的对应关系,帮助开发者精准定位连接问题,掌握蓝牙调试的核心方法。 阅读详情

相关推荐

MuJoCo 机械臂关节空间阻抗控制Impedance实现(附代码)

阻抗控制通过调整关节的刚度和阻尼,让机器人在接触时产生顺应性,减少冲击力,其核心目标是在接触外部载荷时能够自适应调整输出力矩,实现力与位置的协同控制。阻抗控制可以很快的到达设定位置,在此基础上,使用mujoco交互中的施加外力操作,可以看到当外力松开后,机械臂也可以很快的回弹回设定位置。其中self.Kp和self.Kd为固定刚度和阻尼系数,通过修改刚度和阻尼参数,可以变得更柔顺来应对各种场景。注释掉该行后,直接simulate仿真可以看到机械臂控制位置震荡等情况,接下来引入关节空间阻抗控制的代码。

darcsdn 1274

封装JS方法

前言    本篇主要是说明在JS文件中,封装JS比较常用的几种模式。运用1.常见写法。//函数的写法 function run () { alert('常规写法');//这里是你函数的内容 } // 调用 run();2.匿名函数写法 // 匿名函数的写法 var run = function(){ alert('这是一种声明函数的方式,左边是...

玩垃圾的人 3436

Unity中URP下的菲涅尔效果实现(个性化修改)

在上篇文章中,我们实现了 URP 下的菲涅尔基础效果,我们在这篇文章中,对其进行自定义化修改。

楠溪泽岸的博客 2063

javascript的定时器

定时器 Window.setInterval(“函数”,“延时”) Window.setTimeout(“函数”,“延时”) Window.clearInterval(“定时器变量名”) Window.clearTimeout(“定时器变量名”) 在js中有两个函数可以实现定时器的功能,即在某段时间后去执行指定的事件或方法。 这两个函数分别是window.setInterval()和window....

温柔雨哥的博客 507

SC-FDMA

<br />SC-FDMA(Single-carrier Frequency-Division Multiple Access,單載波分頻多工),是LTE的上行鏈路的主流多址。<br />SC-FDMA是單波載(Single-carrier),與OFDMA相比之下具有的較低的PAPR(峰值/平均功率比,peak-to-average power ratio),比多載波的PAPR低1-3dB左右(PAPR是由于多載波在频域叠加引起)。更低的PAPR可以使行動終端(mobile terminal)在發送功效方面

jod的专栏 3299

从AMBA到USB:手把手教你评估和选择Synopsys DesignWare里的免费商用IP

本文详细介绍了如何评估和选择Synopsys DesignWare中的免费商用IP,从AMBA到USB等关键模块。通过技术参数核对、验证环境评估和集成注意事项,帮助工程师高效利用这些经过硅验证的商业级IP,提升SoC设计效率。文章还探讨了免费IP与付费IP的边界策略,避免常见陷阱。

weixin_42683394的博客 297

剖析ES类的Generator函数语法与异步应用

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同 1、基本使用 function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator(); hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', don

逆袭的菜鸟X 309

华为交换机与思科/华三设备LACP对接实战:手把手教你配置链路聚合

本文详细解析了华为交换机与思科、华三设备间的LACP链路聚合配置实战,涵盖核心原理、配置步骤及排错技巧。通过对比不同厂商的实现差异,提供可落地的跨厂商对接方案,助力企业网络工程师高效部署高可靠性链路聚合。

weixin_30836759的博客 423

JavaScript中function的动态执行

由于最近来自重构中的需要,所以深入的研究了JavaScript中function(函数/方法)的动态执行。搜索了一下,发现在网上询问相关问题的人非常多,相应给出的解决方法也是很多的,但却没有深入研究的说明。本人觉得深入的研究并解决function的动态执行问题还是非常有价值的。 本文将从不同的应用情况入手,并由浅入深的给出解决方案与分析。动态执行从服务端返回的JavaScript代码不在本...

weixin_34270606的博客 233

机器学习实战7-基于机器学习算法预测相亲成功率

大家好,我是微学AI,今天给大家介绍一下机器学习实战7-基于机器学习算法预测相亲成功率,随着社会的发展,大家都忙于事业,对自己的终身大事就耽搁了,相亲是一种传统的寻找伴侣的方式,随着时代的发展,相亲的方式也在不断地改变。在这个过程中,了解相亲双方的信息以及预测相亲是否成功变得越来越重要。本文将介绍如何使用随机森林算法对相亲成功进行预测,通过分析男女双方的房子、车子、长相、家庭条件、父母情况、生活习惯、学历、性格、兴趣等因素,来预测相亲是否成功。

微学AI的博客 3034

【深度学习】最强算法之:残差网络(ResNet)

一篇掌握深度学习算法之:残差网络

商务合作 | 面试培训 | 职场规划 ==>主页扫码 7837

​x​ var a=1;var b=2;function run(){ var c=a+b console.log(c)}run()

javascript var a=1; var b=2; function run(){ var c=a+b console.log(c) } run()

paddingC的博客 1800

3、Tone Mapping色调映射(Advanced High Dynamic Range Imaging )

3、Tone Mapping色调映射(Advanced High Dynamic Range Imaging) 如今,大多数可用的显示设备无法本地显示HDR内容。 入门级显示器的对比度仅为200:1。 尽管高端液晶电视具有更高的对比度,但平均对比度约为10,000:1,但通常每个色彩通道的离散度为8位,很少为10位。 这意味着色调限制为255。在过去的二十年中,研究人员花费了大量时间和精力来压缩HDR图像和视频的范围,以便可以在LDR显示器上更“自然”地看到数据。 图3.1 色调映射和真实场景之间.

ISP行业的忠实粉丝 1866

ES6——20. Generator 函数的异步应用

异步编程对 JavaScript 语言太重要。JavaScript 语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可。本章主要介绍 Generator 函数如何完成异步操作。

chtazycdf的博客 1011

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【ES6】Generator函数详解

【ES6】Generator函数详解一、Generator函数简介基本概念函数写法yield关键字介绍二、next方法的参数三、for...of循环四、关于普通throw()与Generator的throw()五、Generator函数的应用【很重要】1、延迟函数2、简化函数的flag(Generator与状态机)3、异步操作的同步化表达4、函数的自动化控制【心生佩服】 引言:从Generato...

十一月廿七风雨大作 7107

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

ES6 中的 generator 函数究竟是什么

ES6 中的 generator 函数介绍

qq_42880714的博客 1445

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

ES6-Generator 函数的异步应用

ES6-Generator 函数的异步应用 前言 异步编程对 JavaScript 语言太重要。JavaScript 语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可。本章主要介绍 Generator 函数如何完成异步操作。 异步编程 所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。 比如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其

weixin_44182099的博客 277

ES6之 Generator 函数的异步应用

1. Generator函数 协程实现:yield暂停,next启动 数据交换和错误处理:yield和next参数,Generator内捕获外部错误 异步任务封装 var fetch = require('node-fetch') function* g() { let res = yield fetch('https://api.github.com/users/github') ...

weixin_41837346的博客 145

js ES6 异步处理之 Promise、Generator 与 async

一、Generator 函数 1、Generator 函数的语法 简介 next 方法的参数 for...of 循环 Generator.prototype.throw() Generator.prototype.return() next()、throw()、return() 的共同点 yield* 表达式 作为对象属性的 Generator 函数 Generator 函数的this 含义 应用 2、Generator 函数的异步应用 二、async 函数 含义 基本用法 语法 as..

青蛙king的博客 1236

ES6 Generator函数异步应用(3)

Generator 函数的异步应用 1.处理异步的传统方法 ES6诞生以前:主要有以下四种方法 回调函数 事件监听 发布/订阅 Promise对象 2.异步 因为js语言的执行环境是单线程的,如果不是用异步,根本无法使用。 异步就是将一个任务分为两段,第一段执行完毕再去执行其他任务,完了之后在回头处理第二段。 同步就是连续执行,如果程序a没执行玩,b只能等待。 3.回调函数 JavaScr...

qq_43955202的博客 317

ES6:Generator函数详解

从另一个角度看,也可以说 Generator 生成了一系列的值,这也就是其名称的来历(在英语中generator”这个词是“生成器”的意思)。上面的代码中,函数 f 如果是普通函数,在为变量 generator 赋值时就会执行。方法时,内部的指针就会从函数的头部或上一次停下来的地方开始执行,直到遇到下一个。方法等于该对象的遍历器对象生成函数,调用该函数会返回该对象的一个遍历器对象。函数运行的不同阶段从外部向内部注入不同的值,从而调整函数行为。上面的代码已经把回调函数改成了直线执行的形式,但是加入了大量。

DZQ1223的博客 1418

es6中的generator函数详解

但是,调用Generator函数后,函数并不执行,返回的也不是函数执行后的结果,而是一个指向内部状态的指针对象。下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。即:每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。function* gen(x){//一个 Generator 函数return y;

2401_89308368的博客 1028

ES6-Generator与异步操作

Generator与异步操作 1.Generator概念 可以把Generator理解成一个状态机(好像React中有很多state),封装了多个内部状态。执行Generator返回的是一个遍历器对象,可以遍历Generator产生的每一个状态。在function后加*就可以声明一个Generator函数。  function* hiGenerator(){ yield 'hi';

柒青衿的博客 3498

ES6 Generator函数 语法 深入理解

a

sinat_30552885的博客 1969

ES6异步函数简单对比

感恩阮一峰老师的ECMAScript 6 入门,其他知识正在陆续学习中,会在该文章中陆续添入。 promise 将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。 含义:简单说就是一个容器,里面包含着一个未来可能结束的事件的结果 特点: 1.对象状态不受外界影响:pending进行中 fulfilled成功 rejected失败。只有异步操作的结果可以决定当前是哪一种状态...

LynnWonder 1084

ES6---Generator函数

ES6---Generator函数一、简介二、yield 表达式三、next 方法的参数四、for...of 循环五、Generator函数异步操作的同步化表达六、Generator.prototype.throw()---函数体外抛出错误七、Generator.prototype.return()---返回给定的值八、next()、throw()、return() 的共同点1. next()是将yield表达式替换成一个值2. throw()是将yield表达式替换成一个throw语句3. return.

赵佳敏的博客 1005
上一篇: ES6第二十章async函数学习笔记
下一篇: redis初学习
跟着大佬学习
博客等级 码龄8年 2粉丝 20原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值