JavaScript Generator异步过度的实现详解

JavaScript Generator异步过度的实现详解

什么是Generator?

Generator是一种特殊的迭代(iteration)构造函数,它使用关键字 yield 来暂停函数执行,让程序流程的控制权让出去,而后再次从函数的断点开始执行。Generator内部可包含多个 yield 语句,每次执行完一个 yield 就将函数暂停,等待下一个指令。

Generator的基础语法

Generator主要使用函数生成器函数的方式,语法如下:

function* generatorFunc() {
  yield 'value1';
  yield 'value2';
  return 'generatorFunc end';
}

当我们使用 generatorFunc() 调用时,只会返回一个迭代器(Iterator)对象,而不是直接执行函数中的语句。

const generator = generatorFunc();

console.log(generator.next()); // {value: 'value1', done: false}
console.log(generator.next()); // {value: 'value2', done: false}
console.log(generator.next()); // {value: 'generatorFunc end', done: true}
console.log(generator.next()); // {value: undefined, done: true}

当程序执行到 yield 时,会暂停代码执行,将 yield 后的值作为迭代器对象的 value 属性,并将 done 设置为 false,等待下一次调用。当函数执行到最后一次 yieldreturn 时,将 done 设置为 true,并返回最后一个值。

Generator的异步应用

Generator的主要应用是作为异步操作的容器。比如,我们要调用多个异步操作,需要使用回调函数嵌套,造成代码可读性降低,而使用Generator可以解决这个问题。

示例一:异步操作的演示

我们模拟一下请求两个API的情况,先看传统的回调函数写法:

function requestApi1(cb) {
  setTimeout(() => {
    cb('response1');
  }, 1000);
}

function requestApi2(cb) {
  setTimeout(() => {
    cb('response2');
  }, 1000);
}

requestApi1(response1 => {
  console.log(response1);
  requestApi2(response2 => {
    console.log(response2);
  });
});

这种回调嵌套的方式非常难以维护,改用Generator的方式:

function* requestApi() {
  const response1 = yield requestApi1;
  console.log(response1);
  const response2 = yield requestApi2;
  console.log(response2);
}

function asyncRequestApi(generator) {
  const iterator = generator();
  const next = response => {
    const {value, done} = iterator.next(response);
    if (!done) {
      value(next);
    }
  };
  next();
}

asyncRequestApi(requestApi);

这种方式,代码可读性明显提高,异步操作之间的关系也更清晰了。

示例二:使用Generator+Promise处理异步请求

我们借助Promise对象来把异步请求改用Promise封装,再结合Generator使用。这种方式将异步操作看作一个单独的Promise,将Generator所负责的线程与异步操作解耦。

function requestApi1() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('response1');
    }, 1000);
  });
}

function requestApi2() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('response2');
    }, 1000);
  });
}

function* requestApi() {
  const response1 = yield requestApi1();
  console.log(response1);
  const response2 = yield requestApi2();
  console.log(response2);
}

function asyncRequestApi(generator) {
  const iterator = generator();
  const next = response => {
    const {value, done} = iterator.next(response);
    if (!done) {
      value.then(next);
    }
  };
  next();
}

asyncRequestApi(requestApi);

总结

Generator提供了一种可控的、分步的方式来处理异步请求,能够解决回调函数嵌套的问题,同时能够改善代码可读性,保证异步操作之间逻辑的清晰性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript Generator异步过度的实现详解 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 动态加载js和css(外部文件)

    动态加载JS和CSS文件是在页面加载过程中向页面动态地添加外部资源文件。它可以帮助我们减少页面加载时间,提高网站性能,使网站更加简洁干净,增强用户体验。下面是完整攻略: 动态加载JS文件 通过DOM创建script标签 使用JavaScript函数 createElement() 和 appendChild() 创建一个新的script标签,将其插入到文档中…

    JavaScript 2023年5月27日
    00
  • Javascript怎样使用SessionStorage和LocalStorage

    使用SessionStorage和LocalStorage可以在客户端存储、读取数据,从而实现一些常见的功能,例如用户登录状态的保持、表单数据的保存等等。SessionStorage一般用于临时保存会话数据,当用户关闭浏览器时会被清除;而LocalStorage可以长期存储,直到用户手动删除或者浏览器清除缓存。 SessionStorage的使用 存储数据 …

    JavaScript 2023年6月11日
    00
  • js判断文件类型大小并给出提示的实现方法

    下面就是“js判断文件类型大小并给出提示的实现方法”的完整攻略: 思路概述 获取文件类型 获取文件大小 判断文件类型和大小,给出提示信息 获取文件类型 文件类型可以通过文件后缀名来判断。可以通过以下方法获取文件后缀名: // 传入文件名,返回文件后缀名 function getFileSuffix(fileName) { var index = fileNa…

    JavaScript 2023年5月27日
    00
  • JavaScript立即执行函数用法解析

    JavaScript中的立即执行函数是指在定义后立即执行的函数。它的语法是使用函数表达式或函数声明的方式定义一个函数,然后紧接着使用括号将其包起来,并在后面添加括号,如下: // 函数表达式方式 (function() { // 立即执行的代码 })(); // 函数声明方式 (function foo() { // 立即执行的代码 })(); 这种立即执行…

    JavaScript 2023年5月27日
    00
  • JS实现的ajax和同源策略(实例讲解)

    当网页需要与服务器进行数据交互时,可以使用JS实现的ajax技术。然而,同源策略限制了网页只能与同一域名下的服务器进行数据交互,从而保证了用户数据的安全性。下面将详细讲解JS实现的ajax和同源策略的完整攻略,包括如何使用ajax发送请求、如何处理响应数据、如何设置同源策略等内容。 AJAX AJAX(Asynchronous JavaScript and …

    JavaScript 2023年6月11日
    00
  • JavaScript保留关键字汇总

    下面是JavaScript保留关键字汇总的完整攻略。 什么是JavaScript保留关键字 JavaScript保留关键字是指被JavaScript编程语言用作内部特定目的的单词或符号。这些单词或符号不能被作为变量名、函数名或标识符等用于代码中。如果这些关键字被用作标识符,代码就会出现编译错误。所以我们在编写JavaScript代码的时候,需要避免使用保留关…

    JavaScript 2023年5月18日
    00
  • js Event对象的5种坐标

    JS Event对象包含5种不同的坐标属性,它们可以用来描述事件的发生位置,这些坐标属性分别是: clientX和clientY pageX和pageY screenX和screenY offsetX和offsetY x和y 下面就逐一介绍这5种坐标属性的含义和使用方法: 1. clientX和clientY clientX和clientY属性用来获取事件的…

    JavaScript 2023年6月10日
    00
  • javascript 代码是如何被压缩的示例代码

    Javascript代码被压缩通常可以分为以下几个步骤: 去除代码中的空格、注释、不必要的换行符等无用字符。 压缩变量名,将长变量名换成短变量名,同时确保不会与其他变量名产生冲突。 压缩函数名,将函数名换成简短的名字。 将一些常见的操作(如+、-、*、/)转换成更短的操作符(如@、^、#、|)。 一些改善性能的代码优化。例如:使用逗号操作符合并多次赋值、将较…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部