ES6学习笔记15 Generator 函数的异步应用

MSDN Win10镜像缺少驱动?这里有全面解决方案 针对MSDN Win10镜像缺少驱动的问题,本文提供了四种解决方案:厂商官网下载驱动程序、利用Windows更新获取驱动、使用第三方驱动更新工具以及使用集成驱动的Win10系统镜像。每种方案都有其优缺点,用户可以根据自己的需求和实际情况选择合适的方案。建议优先考虑官方渠道:官方渠道下载的驱动程序稳定可靠,是解决问题的首选方案。谨慎选择第三方工具:使用第三方工具时,务必选择信誉好、无广告捆绑的工具,并注意保护个人隐私和计算机安全。备份重要数据:在进行系统安装或更新前,务必备份重要数据以防丢失。 阅读详情

异步

所谓”异步”,简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

回调函数

JavaScript 语言对异步编程的实现,就是回调函数。所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。回调函数的英语名字callback,直译过来就是”重新调用”。

fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
  if (err) throw err;
  console.log(data);
});

上述读取文件的函数中,第三个参数就是回调函数,等到读取结果返回后,它才会执行

Generator函数

传统的编程语言使用”协程”来解决异步编程问题,所谓协程,意思是多个线程互相协作,完成异步任务。

协程有点像函数,又有点像线程。它的运行流程大致如下。

  • 第一步,协程A开始执行。
  • 第二步,协程A执行到一半,进入暂停,执行权转移到协程B。
  • 第三步,(一段时间后)协程B交还执行权。
  • 第四步,协程A恢复执行。

上面流程的协程A,就是异步任务,因为它分成两段(或多段)执行。

Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。

function* asyncJob() {
  // ...其他代码
  var f = yield readFile(fileA);
  // ...其他代码
}

异步任务的封装

下面利用Generator函数,执行了一个真实的异步任务

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

上述代码先读取一个远程接口,然后从JSON格式的数据解析信息。上述读取并返回数据结果的过程就是一个异步过程。只有结果返回后,才能输出信息。

执行上述代码的方法如下

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();   //解析数据并返回数据
}).then(function(data){
  g.next(data);    
});

Fetch模块返回的是一Promise对象,因此要用then方法调用下一个next方法,并把data传递给Generator函数,result才能被输出。

可以看到,虽然 Generator 函数将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段),需要自己手动调用next方法。

Thunk函数

Thunk函数是自动执行Generator函数的一种方法。Thunk函数的作用就是将一个多参数的函数,替换为一个只接受回调函数作为参数的单参数函数,有点函数柯里化的感觉

// 正常版本的readFile(多参数版本)
fs.readFile(fileName, callback);

// Thunk版本的readFile(单参数版本)
var Thunk = function (fileName) {
  return function (callback) {
    return fs.readFile(fileName, callback);
  };
};

var readFileThunk = Thunk(fileName);
readFileThunk(callback);

上述经过转换的readFile方法只接受一个回调函数作为参数,这个单参数的版本函数就叫做Thunk函数

下面代码可以将一个函数转换为Thunk函数

// 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);
    }
  };
};

使用上面的转换器,生成fs.readFile的 Thunk 函数。

var readFileThunk = Thunk(fs.readFile);
readFileThunk(fileA)(callback);

在生产环境下,可以使用Thunkify模块转换

$ npm install thunkify  //安装
var thunkify = require('thunkify');
var fs = require('fs');

var read = thunkify(fs.readFile);  //转换
read('package.json')(function(err, str){
  // ...
});

Generator 函数的流程管理

Generator 函数封装了两个异步操作,分别用于读取两个文件,并输出结果。

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

var gen = function* (){
  var r1 = yield readFileThunk('/etc/fstab');
  console.log(r1.toString());
  var r2 = yield readFileThunk('/etc/shells');
  console.log(r2.toString());
};

下面使用回调函数手动执行上面这个Generator函数

var g = gen();

var r1 = g.next();
r1.value(function (err, data) {   //注意,此时r1.value的值为一个Thunk函数
  if (err) throw err;
  var r2 = g.next(data);
  r2.value(function (err, data) {
    if (err) throw err;
    g.next(data);
  });
});

仔细查看上面的代码,可以发现 Generator 函数的执行过程,其实是将同一个回调函数,反复传入next方法的value属性。这使得我们可以用递归来自动完成这个过程。

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

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

  next();
}

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

run(g);

上面代码的run函数,就是一个Generator函数的自动执行器。内部的next函数就是Thunk的回调函数。next函数先将指针移到Generator函数的下一步(gen.next方法),然后判断 Generator 函数是否结束(result.done属性),如果没结束,就将next函数再传入Thunk函数(result.value属性),否则就直接退出。

只要每一个异步操作,都是Thunk函数,我们就可以使用上述的递归方法自动执行Generator函数内部的多个异步操作。

基于Promise对象的自动执行

Thunk 函数并不是 Generator 函数自动执行的唯一方案。因为自动执行的关键是,必须有一种机制,自动控制 Generator 函数的流程,接收和交还程序的执行权。回调函数可以做到这一点,Promise 对象也可以做到这一点。

var fs = require('fs');

var readFile = function(filename){  //将读取文件操作包装为一个函数,返回一个Promise对象  
    return new Promise(function(resolve,reject){   
        fs.readFile(filename,function(error,data){
            if (error) return reject(error);
            return resolve(data);
        }); 
    });
};

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');   //每个yield后面都为一个Promise对象
  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 p = g.next(data);
        if (p.done && p.value === undefined) return;
        p.value.then(function(data){
            next(data);
        });
    }
    next();
}

run(gen);

co模块

该模块用于Generator函数的自动执行

var co = require('co');
co(gen);   

Generator 函数只要传入co函数,就会自动执行

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

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

Generator 就是一个异步操作的容器。它的自动执行需要一种机制,当异步操作有了结果,能够自动交回执行权。有两种方法可以做到这一点:

(1)回调函数。将异步操作包装成 Thunk 函数,在回调函数里面交回执行权

(2)Promise 对象。将异步操作包装成 Promise 对象,用then方法交回执行权。

co 模块其实就是将两种自动执行器(Thunk 函数和 Promise 对象),包装成一个模块。使用 co 的前提条件是,Generator 函数的yield命令后面,只能是 Thunk 函数或 Promise 对象。

co支持并发的异步操作,即允许某些操作同时进行,等到它们全部完成,才进行下一步。这时,要把并发的操作都放在数组或对象里面,跟在yield语句后面。

// 数组的写法
co(function* () {
  var res = yield [
    Promise.resolve(1),
    Promise.resolve(2)
  ];
  console.log(res);
}).catch(onerror);

// 对象的写法
co(function* () {
  var res = yield {
    1: Promise.resolve(1),
    2: Promise.resolve(2),
  };
  console.log(res);
}).catch(onerror);

下面是另一个例子

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

function* somethingAsync(x) {
  // do something async
  return y
}
Vue和Vue-Element-Admin(六):集成中的CORS(跨域资源共享)问题 在vue-element-admin登录集成时候碰到跨域资源共享问题,CORS(Cross-origin resource sharing)是浏览器的技术规范,浏览器可以发起跨域请求但Javascript脚本不能,传统的ajax只能获取在同域名下的资源,但Html5允许ajax发起跨域请求,解决方案有:JSONP、Flash、IFrame、CORS。 一、CORS(跨域资源共享)问题 针对vue-element-admin的登录模块的后端接口完成后,前端调用时候出现报错,因为前端的端口是9527而后. 阅读详情

相关推荐

捷联惯导总结--初始对准,位置标定,INS姿态更新,GPS/INS组合

惯导及组合导航回顾  2018.09.16 今天和17系的同学一起把惯导的流程捋了一遍,为了加深自己的记忆,这里在前面把心得大致列出来。 我们这里只考虑捷联式惯导及松组合 首先拿到惯性传感器(加速度计和陀螺仪)需要对其进行标定,是为了求出零偏,比例因子,交轴耦合这些误差。这些误差有的虽然在出厂时会给出,但是考虑到实际环境不同,还是要做标定。一般采用的是六位置旋转法,针对加速度计和陀螺仪同时...

赤豆几维 5万+

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

为什么使用Generator? 如果依次读取两个以上的文件,就会出现多重嵌套。代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为"回调函数地狱"(callback hell)。 Generator的执行情况 function* gen(x) { var y = yield x + 2; return y; } var g = gen(1); g.next() // { v

oneofprogrammer的博客 283

Linux下OpenFire+Spark即时通讯环境搭建全攻略(含证书错误解决方案)

本文提供了一份详尽的Linux环境下OpenFire服务器与Spark客户端即时通讯系统的搭建与配置全攻略。内容涵盖从环境规划、服务端部署、数据库配置到客户端连接的全流程,并重点解决了Spark连接时常见的证书验证错误问题,为企业构建私有化、高可用的XMPP通讯平台提供了实战指导。

weixin_29251131的博客 165

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

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

chtazycdf的博客 1011

保姆级教程:手把手调试PX4Ctrl的油门映射与姿态控制(附ROS节点配置)

本文提供PX4Ctrl的深度调参指南,涵盖油门映射、姿态控制及ROS节点配置等关键环节。通过详细解析PX4控制器的核心逻辑、递归最小二乘法(RLS)参数估计及状态机设计,帮助开发者优化无人机飞控性能。附实战案例与安全调试建议,适合PX4开发者进阶学习。

weixin_30363981的博客 382

Chapter 7 Linear Voltage Regulators

这一章我们介绍LDO.

2304_76736886的博客 2764

【ES6】Generator函数详解

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

十一月廿七风雨大作 7107

C++实战指南:使用CodeBlocks构建跨平台wxWidgets窗口应用

本文是一份面向C++初学者的实战指南,详细介绍了如何使用CodeBlocks IDE和wxWidgets框架快速构建跨平台的桌面窗口应用。内容涵盖从环境搭建、项目配置到界面设计、事件处理的全流程,重点讲解了如何利用CodeBlocks的开箱即用支持和wxSmith可视化设计器,高效开发具有按钮、菜单、列表等控件的交互式窗口界面程序,帮助读者轻松入门GUI开发。

weixin_29012677的博客 154

ES6 中的 generator 函数究竟是什么

ES6 中的 generator 函数介绍

qq_42880714的博客 1445

uniapp [安卓苹果App端] - 实现获取手机日历读写权限+调用本机日历数据及操作功能+日历中插入事项事件提醒,检测权限手机日历权限是否开启并引导用户同意授权,uniApp app端开启日历授权

uni-app,权限,手机日历权限,安卓Android,苹果ios,uniapp安卓android获取本机日历读写权限使用,uni-app获取日历权限并实现插入事项事件功能 uniapp苹果IOS系统不支持怎么办,判断权限,权限被拒绝了怎么办,获取日历权限报错,读取日历数据农历阴历并操作插入移除,给用户手机日历中放入一条提示,UniApp调用日历进行读写,打包上架后如何获取,安卓ios权限检测,安卓和ios权限获取,uniapp的APP端日历读写权限与使用示例代码,如何开启日历权限,日历的新增事项和删除,判

🏆 前端领域优质创作者 1万+

14 Prompt 的边界:什么时候必须用 RAG 或微调

Prompt 不是万能解法。本文用“改输入、补知识、改模型”这条主线,讲清什么时候继续优化 Prompt,什么时候必须引入 RAG、工具调用或微调,帮助你避免用重技术掩盖轻问题。

老于的笔记的专栏 209

ES6-Generator 函数的异步应用

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

weixin_44182099的博客 277

YooAsset 学习

YooAssets使用教程

weixin_44884538的博客 1659

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

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

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

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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学习笔记18--Generator 函数的异步应用

异步编程的方法: (1)回调函数 (2)事件监听 (3)发布/订阅 (4)Promise 对象 (5)新增:Generator 函数 协程的Generator 函数实现 协程 概念:多个线程互相合作,完成异步任务。 协程运行流程: (1)协程 A 开始执行 (2)协程 A 执行到一半,进入到暂停,执行权转移到 协程 B (3)一段时间后,协程 B 交还 执行权 (4)协程 A 恢复执行。 Generator 函数是协程在ES6 的实现,最大特点就是可以交出函数的执行权(即..

zcy8023u的博客 248

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-Generator与异步应用

Generator函数简介 基本概念 语法上理解 定义形式上理解 基本示例 Generator和iterator的关联 yield语句 yield语句使用的注意事项 yield语句和return语句的比较 yield* 语句 yield* + 无return的Generator函数 yield* + 有return的Generator函数 yield* + array/string/Set/Map/nodeList/arguments next方法 next方法的运行逻辑 next方..

爱代码的小海的博客 574

ES6 入门教程 20 Generator 函数的异步应用 20.4 Thunk 函数

ES6 入门教程 20 Generator 函数的异步应用 20.4 Thunk 函数

代码改变世界 309

ES6之 Generator 函数

generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以。

猫老板的豆 848
上一篇: ES6学习笔记14 Generator 函数
下一篇: 郝夫曼(Huffman)树及其应用
PAT-python-zjw
博客等级 码龄10年 381粉丝 408原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值