什么是 Redux-Saga?2025 年 4 月 5 日 | 阅读 11 分钟 ![]() Redux-Saga 是一个主要用于处理应用程序副作用的库,例如异步数据获取和访问不纯的浏览器缓存。它易于管理且执行效率高。使用 Redux-Saga,可以轻松测试并毫不费力地处理失败。 Redux-Saga 可以被认为是帮助使用 Redux 构建的应用程序与 API 等外部依赖进行通信并保持同步的一种有组织的方式。总的来说,它是一个中间件库,可用于向外部服务发出 HTTP 请求、执行 I/O 操作以及访问浏览器存储。Redux-Saga 的强大之处在于能够以一种更容易被开发者管理的方式来组织和管理副作用。 在本教程中,您将从头开始了解 Redux-Saga 及其相关的一切。为了方便您理解,我们将使用 GitHub 上 Redux 仓库中的一个简单计数器。这将易于理解,无需担心过多的细节。 设置 Redux-Saga要获得 Redux-Saga 的实践经验,您需要先在系统上进行设置。首先,您需要克隆 GitHub 仓库;URL 如下。 克隆完给定的 GitHub 仓库后,使用以下命令并按 Enter 键。 完成上述步骤后,下一步是运行应用程序,这可以通过使用以下命令来完成。 一旦 NPM 启动服务器,应用程序将开始运行。该应用程序包含两个基本用例,即用于增加或减少计数器的两个按钮。如果遇到任何问题,请重复相同的命令并继续。 现在,我们将创建您的第一个 Saga。考虑到您是初学者,您可能会像传统方式一样创建一个简单的“Hello World”版本的 Saga。如果一切顺利,您将看到两个按钮以及显示计数器值为 0 的消息。要继续创建应用程序,您需要编写一些 JavaScript 函数并将它们保存在下面。 上面的函数只是返回并显示“Hello Sagas!”消息。因此,要运行 Saga,您需要创建一个带有 Saga 列表的中间件。在上面的代码中,只有一个 Saga。您需要创建多个这样的 Saga 来连接到中间件。因此,您的 main.js 文件应包含以下更改。 在上面的代码片段中,您首先需要从 ./sagas 模块中的应用程序导入 Saga。下一步是使用 **createSagaMiddleware** 函数创建一个中间件,并从 **redux-saga** 库导出它。 在运行 **helloSaga** 之前,您必须使用 **applyMiddleware** 方法将中间件连接到 store。然后,要启动 Saga,您将使用 **sagaMiddleware.run(helloSaga)** 函数。 创建异步调用Redux Saga 使用 **ES6 生成器**函数进行异步调用。这些生成器允许将同步编写的代码转换为异步调用。此外,在每次异步调用时,生成器都会暂停调用,直到前一个调用完成。 让我们通过向计数器添加一些内容来继续。为了说明和理解异步调用,您必须创建另一个按钮,每次单击时该按钮会使计数器增加 1 秒。要提供该附加按钮,请使用 **onIncrementAsync** 为 UI 组件创建一个回调,如下所示。 完成上述步骤后,下一个任务是将组件的 **onIncremenAsync** 连接到 Store 操作。因此,如下所示修改 **main.js** 文件。 需要注意的是,与 **redux-thunk** 不同,您使用的组件仅分派对象操作。因此,您需要使用另一个执行异步调用的 Saga。在这种情况下,您需要启动一个任务,该任务将在计数器增加之前等待 1 秒。为此,请将以下代码添加到您的 main.js 文件中。 在上面的代码片段中,您创建了一个返回 **Promise** 的延迟函数。Promise 将在几毫秒后解析。然后,您实现了该函数来阻塞生成器。 准确地说,saga 始终被视为生成器函数。它们的主要目的是为 redux-saga 中间件生成对象。生成的对象是供中间件解释的指令。因此,Promise 作为对象传递给中间件,并在 Promise 完成之前暂停 Saga。在上面的代码中,增量同步 Saga 在 Promise 解析为 1 秒时暂停。 一旦 Promise 解析,Saga 将被中间件恢复。因此,在上面的示例中,下一个语句会发出另一个对象,因为它从 **({type: 'INCREMENT'})** 调用而来,并且在分派增量操作时由中间件指示。 下一步是通过调用 Effect 来执行的。Effect 只是包含中间件指令的对象。每当中间件从 Saga 中检索到 Effect 时,Saga 都会自动暂停,直到满足要求。总结代码,增量同步 Saga 仅睡眠 1 秒,然后分派增量操作。接下来,创建另一个 Saga **watchIncrementAsync**。该辅助函数监听每个分派的 **INCREMENT_ASYNC** 并每次运行 **incrementAsync**。 现在,既然两个 saga 都已成功创建,您需要将它们一起启动。为此,您需要添加 **rootSaga** 来启动所有其他 Saga。在同一个文件中,复制下面的代码片段。 上面的代码通过同时调用 **helloSaga** 和 **watchIncrementAsync** 来创建一个数组。这通常意味着将有两个生成器并行运行。最好在 main.js 文件中使用根 Saga 来调用 **sagaMiddleware.run** 方法。这可以通过以下代码片段实现。 如前所述,**incrementAsync** 是一个生成器函数。每当它运行时,它都会输出一个迭代器对象,而迭代器的 **next** 方法返回另一个对象,如下所示。 该对象包含给定表达式的字段,这最终表明生成器已终止,或者可能还有更多表达式正在完成。在您的情况下,增量同步会通过提供的生成器生成两个值。 也可以通过生成器的 next 方法调用它。结果将如下所示。 对于前两次调用,会生成所产生表达式的结果。在第三次调用时,由于只创建了两个 Saga,即使字段设置为 true,它也不会产生任何值。此外,由于增量同步生成器不返回任何内容,因此文件保持未定义。 在遵循了上述所有步骤后,您就可以测试 **incrementAsync** 中存在的逻辑了。您需要迭代生成器并返回生成器生成的值。这可以通过以下方式完成。 测试时可能会出现一个问题。延迟的返回值在测试机制中无法保证。您不能使用 Promises 来确保输入正常值。因此,为了解决这个问题,Redux-Saga 提供了一个方法。该方法涉及直接调用 **incrementAsync** 中的 **delay(1000)** 函数,以使后续的深度比较成为可能。 在上面的代码片段中,您可能会注意到,使用的是 yield call(delay,1000) 而不是 delay(1000)。在第一种情况下,表达式具有 **delay(1000)**,在传递给下一个调用者之前对其进行评估。下一个调用者可能是代码运行时调用的中间件。它甚至可以测试运行生成器函数并返回它的代码。这就是为什么在第一种情况下调用者会收到一个 Promise。 在第二种情况下,请注意使用了表达式 **call(delay,1000)** 来获取下一个调用的调用者。它只是返回一个 Effect,该 Effect 建议中间件根据提供的参数调用一个函数。返回的唯一纯 JavaScript 对象是因为它既不放置也不执行任何分派,甚至不自行执行异步调用。总而言之,会返回以下结果。 这意味着当中间件找到产生的 Effect 时,它会简单地满足它。如果存在 **PUT** Effect,那么将向 Store 分派另一个。如果存在 **CALL**,则将调用该函数。Effect 的创建和执行之间的这种精细分离使得生成器更容易测试。实现 Effect 后的最终代码片段如下所示。 call 和 put 只是纯 JavaScript 对象,可以随时用于上面的代码片段的相同函数。因此,为了测试应用于 **incrementAsync** 的逻辑,您需要反复迭代生成器,使用 **deepEqual** 方法来测试值。既然您已经完成了 Redux-Saga 的概念及其实际实现,让我们使用下面的命令对其进行测试。 词汇表到目前为止,我们已经讨论了 Redux-Saga 的概述,让我们看看与它相关的一些核心术语。 效果在 Redux-Saga 中,Effect 被定义为一个纯 JavaScript 对象,其中包含一些将由 Saga 中间件执行的指令。 可以通过包含 Redux-Saga 库提供的工厂函数来创建 Effect。例如,如果您想使用 call(myfunction, 'argument1', 'arguement2') 来为中间件提供调用函数的指令,生成器将执行该函数并返回一个 Effect。 任务任务可以定义为在后台运行的进程。在基于 Redux-Saga 的应用程序中,存在多个在后台并行运行的进程。通过简单地调用 fork 函数即可创建一个任务,其示例可以通过下面的代码片段显示。 阻塞/非阻塞调用在 Redux-Saga 中阻塞调用会导致创建一个 Effect,并且该 Effect 会等待执行完成,从而阻止下一个等待执行的指令,一旦当前场景成功执行并产生一个生成器。 另一方面,Redux-Saga 中的非阻塞调用意味着在 Effect 产生后 Saga 将自动恢复。可以通过下面的示例来演示这两种调用的示例。 Watcher/Worker (监视器/工作器)Watcher/Worker 指的是组织流程控制的正确方法。在此过程中,使用两个单独的 Saga。监视器负责分派环境操作,并为每个操作使用 fork 函数。另一方面,工作器负责处理所有操作并终止。Worker/Watcher 的应用可以通过以下示例显示。 总结在本教程中,您了解了 Redux-Saga 及其在应用程序及其整体开发过程中至关重要的几个最重要因素。在后面的部分中,您看到了 Effect 和 Generator 在定义 Redux-Saga 的重要方面所起的典型作用。Redux-Saga 最初是一个库,它能够有效地在后台运行任务,从而使应用程序开发的前台进程不会受到排他性的影响。 |
我们请求您订阅我们的新闻通讯以获取最新更新。