Redux Middleware 详解:手把手教你实现一个 Logger

Redux Middleware 是什么

当我们使用 Redux 时,我们知道 Reducer 是实现数据流的核心。然而,在实践中,我们难免需要额外的功能,例如日志记录、错误处理、异步操作等等,Redux Middleware 就是为了实现这些额外功能而被引入的中间件。

Redux Middleware 是一些函数,它们可以在 action 发送到 reducer 之前或之后拦截它们,并且可以在拦截时进行一些额外的操作。Redux Middleware 包含一系列预定义的函数,也可以自定义函数以实现独特的功能。

Middleware 在 Redux 架构中的角色

Middleware 在 Redux 架构中扮演一个非常特殊且重要的角色,每个 Middleware 连接着 action、reducer 和 state,并处理这些元素主要的数据流。

在 Redux 中,所有的 action 都会经过每个 Middleware 依次处理,最后到达 reducer。在 action 到达 reducer 的过程中,Middleware 可以修改 action、阻塞 action 或直接转发 action 及引起 side effect。因此,每个 Middleware 处理和传递 action 都是非常关键的,也是构建可扩展和可定制的 Redux 应用程序的关键之一。

在 Middleware 中,我们通常会用到 Redux 提供的 enhancer 函数 applyMiddleware(),由 applyMiddleware() 返回的函数,可以使我们更方便地书写 Middleware,在应用程序的 store 上安装应用 Middleware。

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk, logger)
);

如何自定义 Middleware

接下来,我们来手动实现一个简单的 Logger Middleware,以此来认识并深入理解 Middleware 的实现原理。

Logger Middleware 原理

Logger Middleware 实现日志记录的功能,例如记录每次 action 发送到 reducer 的状态信息、记录 action 发送和 reducer 响应的时间、记录 action 执行的结果等等。

为此,我们可以编写一个函数和 enhancer 函数来实现 Logger Middleware 的目标:

  1. 拦截接收到的 action,记录 payload、类型,以及时间戳;
  2. 将 action 和状态数据输出到控制台;
  3. 将新状态返回给下一个 Middleware,以便按照正常的数据流程进行操作。

Logger Middleware 代码实现

const loggerMiddleware = store => next => action => {
  const { type, payload } = action;
  const timestamp = new Date().toLocaleString();
  console.log(`[${timestamp}] Action: ${type}, Payload: `, payload);

  const result = next(action);

  console.log(`[${timestamp}] Next State: `, store.getState());

  return result;
};

上面的代码实现了一个中间件,它用于记录 action 的类型、payload 和时间,同时输出新状态到控制台。

以上代码分为三部分:

  1. const loggerMiddleware = ...,定义函数 loggerMiddleware,并搭建了洋葱模型,接收 store、next 和 action,调用 next(action) 时,实际上是将 action 传递给了下一个 Middleware。
  2. const {type, payload} = action; ...,解构出 action 的类型和 payload,以及当前时间,输出日志。
  3. return result;,返回 next(action) 的结果,使程序可以按正常逻辑继续执行。

Logger Middleware 安装和测试

需要注意习惯性的把自定义的 Middleware 安装到 store 中,使它可以拦截 state 的流动。

import {createStore, applyMiddleware} from 'redux';
import rootReducer from './reducers';
import loggerMiddleware from './middleware/loggerMiddleware';

const store = createStore(rootReducer, applyMiddleware(loggerMiddleware));

最后,我们用一个示例来测试 Logger Middleware:

const ADD_TODO = 'ADD_TODO';

const addTodo = (text) => ({
  type: ADD_TODO,
  payload: {text}
});

const rootReducer = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload.text];
    default:
      return state;
  }
};

const store = createStore(rootReducer, applyMiddleware(loggerMiddleware));

store.dispatch(addTodo('Learn Redux'));
// [2021-12-30 20:28:59] Action: ADD_TODO, Payload:  {text: "Learn Redux"}
// [2021-12-30 20:28:59] Next State:  ["Learn Redux"]

在 console 中,我们看到了添加新 Todo 的时间、状态和内容。

总结

Redux Middleware 是实现数据流附加功能的关键组成部分,在实战中,我们常常通过应用 Middleware 来拦截和修改 action,进而实现日志记录、异步操作等功能。

我们了解了 Middleware 在 Redux 架构中的角色,并学习了如何自己创建 Middleware。还需要注意的是,我们需要把 Middleware 安装到 store 中,才能发挥 Middleware 的作用。

最后,我建议大家在实践中多动手,尝试自己编写一些有意思的 Middleware,并深入理解 Redux Middleware 在复杂应用程序中的各种使用方法。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a28b50add4f0e0ffaa9f57


纠错反馈