Node.js 生成器与回调函数对比

在本教程中,我们将学习生成器及其与回调函数的区别。

什么是生成器?

生成器在最近的 Node.js 中变得相当有名,这可能归因于它们的功能。

  • 生成器是可以在稍后暂停和恢复的函数执行。
  • 生成器在执行诸如“惰性求值”之类的概念时很有用。这基本上意味着通过暂停执行并根据需要恢复执行,我们可以仅在需要时拉取值。

生成器具有以下 2 个关键方法。

  1. Yield 方法 – Yield 方法在函数中使用,用于在调用 yield 方法的特定行暂停函数执行。
  2. Next 方法 – 此方法从主应用程序调用,用于恢复具有 yield 方法的函数的执行。函数执行将继续,直到下一个 yield 方法或直到函数末尾。

让我们看一个如何使用生成器的示例。

在我们的示例中,我们将有一个简单的 Add 函数来添加两个数字,但我们会不断地在不同的点暂停函数执行,以展示生成器如何使用。

Node.js Generators

function* Add(x) {
   yield x + 1;
   var y = yield(null);
   y = 6
   return x + y;
}

var gen = Add(5);

gen.next();

gen.next(); 

代码解释

  1. 第一步是定义我们的生成器“函数”。请注意,这是通过在 function 关键字后添加“*”来完成的。然后我们定义一个名为 Add 的函数,它接受一个 x 参数。
  2. Yield 关键字是生成器特有的。这使其成为在函数中间暂停的强大构造。因此,此时函数执行将暂停,直到我们调用 next() 函数,该函数将在第 4 步中完成。此时,x 的值将变为 6,函数执行将停止。
  3. 在这里,我们首次调用生成器函数并将 5 的值传递给我们的 Add 函数。此值将替换到我们 Add 函数的 x 参数中。
  4. 一旦我们调用 next() 函数,Add() 函数将恢复执行。当下一条语句 var y= yield(null) 执行时,Add() 函数将再次停止执行。
  5. 现在,再次调用 next() 函数后,将运行下一条语句,并将 x=5 和 y=6 的组合值相加并返回。

回调函数与生成器

生成器用于解决所谓的“回调地狱”问题。有时,在 Node.js 应用程序开发过程中,回调函数会变得如此嵌套,以至于使用回调函数变得非常复杂。

这就是生成器派上用场的地方。其中一个最常见的例子是创建计时器函数。

让我们看下面的示例,了解生成器如何比回调函数更有用。

我们的示例将创建一个简单的延迟函数。然后,我们希望调用此函数,并加入 1000、2000 和 3000 毫秒的延迟。

步骤 1) 定义带有必要延迟代码的回调函数。

Callbacks vs. Generators

function Timedelay(ptime, callback) {

setTimeout(function() {
  
    callback("Pausing for " + ptime);
    
  }, time);
}

代码解释

  1. 这里我们创建一个名为 Timedelay 的函数,它带有一个名为 ptime 的参数。这将接受我们在应用程序中引入的必要延迟。
  2. 下一步是创建一个消息,该消息将显示给用户,告知应用程序将暂停这么多毫秒。

步骤 2) 现在,让我们看看如果我们要引入回调函数的代码。假设我们想根据 1000、2000 和 3000 毫秒的值引入回调,下面的代码显示了我们如何使用回调来实现这些。

Callbacks vs. Generators

Timedelay(1000, function(message) {
  
  console.log(msg);
  Timedelay(2000, function(message) {
    
    console.log(msg);
    Timedelay(3000, function(message) {
      
      console.log(msg);
  })
  })
})

代码解释

  1. 我们将 Timedelay 作为回调函数调用,值为 1000。
  2. 接下来,我们想再次调用 Timedelay 函数,值为 2000。
  3. 最后,我们想再次调用 Timedelay 函数,值为 3000。

从上面的代码可以看出,当我们开始多次调用函数时,它会变得更加混乱。

步骤 3) 现在让我们看看如何使用生成器来实现相同的代码。从下面的代码中,您现在可以看到使用生成器实现 Timedelay 函数变得多么简单。

Callbacks vs. Generators

function* Messages() {
  console,log(yield(Timedelay(1000, function(){})));
  console,log(yield(Timedelay(2000, function(){})));
  console,log(yield(Timedelay(3000, function(){})));
}

代码解释

  1. 我们首先定义一个将用于调用 Timedelay 函数的生成器函数。
  2. 我们将 Yield 函数与 Timedelay 函数一起调用,参数值为 1000。
  3. 然后,我们将 Yield 函数与 Timedelay 函数一起调用,参数值为 2000。
  4. 最后,我们将 Yield 函数与 Timedelay 函数一起调用,参数值为 3000。

摘要

生成器还可用于缓解嵌套回调的问题,并有助于消除所谓的“回调地狱”。生成器用于暂停函数的处理。这可以通过在异步函数中使用“yield”方法来完成。