深入理解 JavaScript 中的 async function*、function*`和 async function 对比function* 和 async function *

深入理解 JavaScript 中的 async function*function*async function

在现代 JavaScript 编程中,异步操作和生成器函数是两个非常重要的概念。它们可以帮助我们更有效地处理异步流程和可迭代的数据序列。本文将深入探讨 function*(生成器函数)、async function(异步函数)以及它们的结合——async function*(异步生成器函数),并重点详细说明 async function*function* 的区别。


目录

  1. 生成器函数(function*
  2. 异步函数(async function
  3. 异步生成器函数(async function*
  4. async function*function* 的区别
  5. 总结

生成器函数(function*

什么是生成器函数

生成器函数是 ES6 引入的一种特殊函数,使用 function* 声明。它可以在执行过程中暂停和恢复,通过 yield 关键字产生一系列值。

特点:

  • 可暂停执行:生成器函数可以在 yield 表达式处暂停。
  • 返回一个迭代器对象:调用生成器函数会返回一个迭代器,可用于遍历生成的值。

生成器函数的用法

基本语法:

function* generatorFunction() {
  // 生成器函数主体
}

示例:

function* numberGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = numberGenerator();

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

说明:

  • 每次调用 next(),生成器函数会从上一次暂停的地方继续执行,直到遇到下一个 yield

异步函数(async function

什么是异步函数

异步函数是 ES2017 引入的一种语法,用于简化基于 Promise 的异步操作。使用 async 关键字声明,内部可以使用 await 等待一个 Promise 的结果。

特点:

  • 简化异步代码:使异步代码看起来像同步代码,提高可读性。
  • 返回 Promise:异步函数始终返回一个 Promise。

异步函数的用法

基本语法:

async function asyncFunction() {
  // 异步函数主体
}

示例:

async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

fetchData().then(data => {
  console.log(data);
});

说明:

  • 使用 await 等待异步操作完成,获取结果。
  • 异步函数返回的 Promise,可以使用 .then()await 进行处理。

异步生成器函数(async function*

什么是异步生成器函数

异步生成器函数结合了生成器函数和异步函数的特性。使用 async function* 声明,可以在生成器函数中使用 await,并异步地 yield 值。

特点:

  • 异步迭代:可用于处理异步数据流。
  • 返回异步迭代器:生成的迭代器对象符合异步迭代器协议,可用于 for await...of 循环。

异步生成器函数的用法

基本语法:

async function* asyncGeneratorFunction() {
  // 异步生成器函数主体
}

示例:

async function* asyncNumberGenerator() {
  let i = 0;
  while (i < 3) {
    await new Promise(resolve => setTimeout(resolve, 1000)); // 模拟异步操作
    yield i++;
  }
}

(async () => {
  for await (let num of asyncNumberGenerator()) {
    console.log(num); // 每秒输出一个数字:0, 1, 2
  }
})();

说明:

  • 使用 for await...of 循环遍历异步生成器函数返回的异步迭代器。
  • 可以在函数内部使用 await 等待异步操作,然后 yield 结果。

async function*function* 的区别

返回值的区别

  • function* 返回同步迭代器

    调用 function* 声明的生成器函数,会返回一个同步迭代器对象。该迭代器符合可迭代协议,可用于 for...of 循环。

    function* generatorFunction() {
      yield 1;
      yield 2;
    }
    
    const iterator = generatorFunction();
    console.log(iterator.next()); // { value: 1, done: false }
    
  • async function* 返回异步迭代器

    调用 async function* 声明的异步生成器函数,会返回一个异步迭代器对象。该迭代器符合异步可迭代协议,需要使用 for await...of 循环遍历。

    async function* asyncGeneratorFunction() {
      yield 1;
      yield 2;
    }
    
    const asyncIterator = asyncGeneratorFunction();
    console.log(await asyncIterator.next()); // { value: 1, done: false }
    

处理异步操作的能力

  • function* 不能直接处理异步操作

    function* 中,如果需要处理异步操作,不能直接使用 await。需要使用额外的逻辑,如返回 Promise 或通过外部控制。

    function* generatorFunction() {
      const data = yield fetchData(); // 无法直接使用 await
    }
    

    示例:

    function* fetchGenerator() {
      const dataPromise = fetch('https://api.example.com/data');
      const data = yield dataPromise;
      console.log(data);
    }
    
    const gen = fetchGenerator();
    const dataPromise = gen.next().value;
    
    dataPromise.then(response => response.json())
      .then(data => gen.next(data));
    
  • async function* 可以直接使用 await

    async function* 中,可以直接使用 await 等待异步操作完成,然后再 yield 结果。

    async function* asyncGeneratorFunction() {
      const data = await fetchData();
      yield data;
    }
    

    示例:

    async function* fetchAsyncGenerator() {
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      yield data;
    }
    
    (async () => {
      for await (let data of fetchAsyncGenerator()) {
        console.log(data);
      }
    })();
    

迭代方式的不同

  • function* 使用同步迭代

    使用 for...of 循环遍历生成器函数返回的迭代器。

    function* generatorFunction() {
      yield 1;
      yield 2;
    }
    
    for (let value of generatorFunction()) {
      console.log(value); // 输出 1 和 2
    }
    
  • async function* 使用异步迭代

    使用 for await...of 循环遍历异步生成器函数返回的异步迭代器。

    async function* asyncGeneratorFunction() {
      yield 1;
      yield 2;
    }
    
    (async () => {
      for await (let value of asyncGeneratorFunction()) {
        console.log(value); // 输出 1 和 2
      }
    })();
    

应用场景的差异

  • function* 适用于同步数据序列

    当需要生成一系列同步的、可迭代的数据时,使用生成器函数是非常方便的选择。

    示例:

    function* idGenerator() {
      let id = 0;
      while (true) {
        yield id++;
      }
    }
    
    const gen = idGenerator();
    console.log(gen.next().value); // 输出 0
    console.log(gen.next().value); // 输出 1
    
  • async function* 适用于异步数据流

    当需要逐步获取异步数据(如网络请求、文件读取)并以可迭代的方式处理时,异步生成器函数是理想的工具。

    示例:

    async function* readLines(file) {
      let reader = file.getReader();
      let decoder = new TextDecoder('utf-8');
      let { done, value } = await reader.read();
    
      while (!done) {
        yield decoder.decode(value);
        ({ done, value } = await reader.read());
      }
    }
    
    (async () => {
      for await (let line of readLines(someFile)) {
        console.log(line);
      }
    })();
    

总结

  • 生成器函数(function*:适用于需要自定义迭代行为的同步场景。不能直接处理异步操作,返回同步迭代器。
  • 异步函数(async function:简化异步操作,提高代码的可读性和可维护性。返回 Promise,不适用于需要迭代的场景。
  • 异步生成器函数(async function*:结合了生成器和异步函数的特性,适用于处理异步数据流。可以直接使用 await,返回异步迭代器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值