理解ES6中的Generator

ops/2024/10/20 17:51:02/

Generator是ES6引入的一种特殊的函数,允许函数执行过程可以暂停和恢复,具有异步编程的优势。通过function*声明生成器函数,使用yield关键字来暂停函数执行,并通过next()方法来恢复执行。

特点与机制

  1. 暂停执行yield关键字可以将函数执行暂时中断,返回值给调用者,直到调用next()时恢复继续执行。
  2. 状态保存:每次暂停执行时,生成器函数会保存当前状态,返回一个Iterator对象来逐步获取执行结果。
  3. 异步控制:生成器与Promise结合,可以轻松实现异步流程控制。

基本用法

javascript">function* generatorExample() {yield 'Step 1';yield 'Step 2';yield 'Step 3';
}const gen = generatorExample();
console.log(gen.next().value); // 输出 'Step 1'
console.log(gen.next().value); // 输出 'Step 2'
console.log(gen.next().value); // 输出 'Step 3'
console.log(gen.next().done);  // 输出 true

使用场景

  1. 异步任务的执行控制:生成器可以代替回调函数进行异步任务控制,通过暂停函数实现复杂的异步流程,避免回调地狱。

    javascript">function* asyncFlow() {const result = yield fetch('/api/data');console.log(result);
    }
    
  2. 实现无限序列:生成器可以产生无限的序列,按需生成数据,而不是一次性全部创建。

    javascript">function* infiniteSequence() {let i = 0;while (true) {yield i++;}
    }
    
  3. 迭代器的实现:生成器可以简化自定义迭代器的编写,轻松实现复杂的数据流迭代。

优点

  • 生成器使得异步流程更加可读和直观,适用于需要控制执行顺序和节奏的场景。
  • 函数的执行过程可控,可以暂停、恢复、甚至外部传递值。

缺点

  • 对于不熟悉生成器的人,语法和概念相对复杂,在某些情况下可能不如async/await直观。

让我们来看一个在前端开发任务中使用 Generator 的简单案例。假设我们需要从服务器加载一些数据,并且在每次数据加载完成之后执行某些操作,如更新UI或者触发其他请求。我们可以使用 Generator 来管理这个流程。

示例:模拟异步数据加载

首先,我们需要一个模拟的异步请求函数:

javascript">function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));
}function mockFetch(url) {return sleep(1000).then(() => ({url,data: `Data fetched from ${url}`}));
}

接下来,我们将使用 Generator 来管理请求和UI更新逻辑:

javascript">function* fetchDataAndRender(urls) {for (let url of urls) {yield renderLoadingIndicator(true); // 显示加载指示器let response = yield mockFetch(url); // 模拟异步请求yield renderLoadingIndicator(false); // 隐藏加载指示器renderData(response.data); // 渲染数据}
}// 假设的渲染函数
function renderLoadingIndicator(isLoading) {console.log(isLoading ? 'Loading...' : 'Loaded.');
}function renderData(data) {console.log('Rendering:', data);
}// 执行 Generator
function runGenerator(generatorFunction, urls) {const generator = generatorFunction(urls);function send(value) {try {const result = generator.next(value);if (result.done) {console.log('All requests completed!');} else {result.value.then(send);}} catch (err) {console.error('Error:', err);}}send();
}const urls = ['https://api.example.com/data1','https://api.example.com/data2','https://api.example.com/data3'
];runGenerator(fetchDataAndRender, urls);

在这个案例中,我们定义了一个 fetchDataAndRender Generator 函数,它接受一个 URL 数组,并依次处理每个 URL。每次请求之前显示加载指示器,请求完成后隐藏加载指示器并渲染数据。

runGenerator 函数负责启动 Generator 并处理 Generator 返回的 Promise 对象,这样可以确保按照 Generator 定义的顺序正确地执行每一步。

这种模式可以方便地扩展到更复杂的流程管理,例如错误处理、分支逻辑等。通过这种方式,你可以将异步操作组织得更加清晰,并且易于理解和维护。

ES6中的生成器是处理异步编程的有力工具,它让复杂的控制流变得更加简洁和清晰。


http://www.ppmy.cn/ops/127043.html

相关文章

基于FPGA的以太网设计(三)

通过前文介绍了RGMII接口时序我们可以知道,RGMII接口是在时钟信号的上升沿和下降沿均进行数据的传输,而FPGA则在时钟的单沿传输数据,因此我们需要编写代码将RGMII接口转换为GMII接口。 由于前面的介绍我们知道RTL8211默认工作在延时状态&…

【STM32】C语言复习以及底层寄存器映射

位操作 &运算 通过与一堆1111,来筛选想要的位并保留 通过与一堆0000,来将不想要的位置置0 110011011 111111000 |运算 通过或一堆1111,用来全置1 通过或一堆0000,来筛选想要的位 右移 2 >> 1:相当…

JSONArray根据指定字段去重

JSONArray dataList new JSONArray();这儿省略dataList 加数据的过程 dataList new JSONArray(dataList.stream().distinct().collect(Collectors.toList())); Set<String> timestamps new HashSet<>();根据时间字段去重 dataList dataList.stream().map(obj -…

【日志】关于多益网申

2024.10.19 早先听闻多益的测试题非常抽象&#xff0c;凡是测过的人都说太抽象了&#xff0c;我还以为他考我各种算法或者编程语言呢。我今天也去做了一下&#xff0c;测试题里面大多都考些计算题&#xff0c;找规律题&#xff0c;判断推理题&#xff0c;还有一些图形转换&…

基于预测算法的航班离港延误系统

毕业设计不知道做什么&#xff1f;想找一个结合算法与应用的项目&#xff1f;那你绝对不能错过这个"基于预测算法的航班离港延误系统"&#xff01;✈️&#x1f4ca; 项目简介&#xff1a; 这个系统专注于航班离港的延误预测&#xff0c;通过强大的神经网络技术对大…

Linux 中文件的权限说明

目录 一&#xff1a;文件权限类型二&#xff1a;默认权限管理1. 查看当前用户的umask值2. 修改当前用户的umask值3. 根据umask计算默认权限 三&#xff1a;普通权限管理1. 三种普通权限说明1.1 对于非目录文件来说1.2 对于目录文件来说 2. 查看某个文件的权限信息2.1 使用 ls -…

算法Day-4

24. 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,…

搜维尔科技:使用Manus Primel Xsens数据手套直接在Xsens及其插件中捕获手指数据

使用Manus Primel Xsens数据手套直接在Xsens及其插件中捕获手指数据 搜维尔科技&#xff1a;使用Manus Primel Xsens数据手套直接在Xsens及其插件中捕获手指数据