8 redux Middleware(中间件)

本文探讨了如何通过构建Middleware解决记录日志和创建崩溃报告的问题,展示了从分析问题到解决方案的思维过程,介绍了Middleware的基本概念及其在Redux中的应用。

理解 Middleware

正因为 middleware 可以完成包括异步 API 调用在内的各种事情。我们将以记录日志和创建崩溃报告为例,引导你体会从分析问题到通过构建 middleware 解决问题的思维过程。

 

问题: 记录日志

每次state更新时,如何记录其值

尝试 #1: 手动记录

let action = addTodo('Use Redux')

 

console.log('dispatching', action)

store.dispatch(action)

console.log('next state', store.getState())

 

尝试 #2: 封装 Dispatch

你可以将上面的操作抽取成一个函数:

function dispatchAndLog(store, action) {

  console.log('dispatching', action)

  store.dispatch(action)

  console.log('next state', store.getState())

}

然后用它替换 store.dispatch():

dispatchAndLog(store, addTodo('Use Redux'))

 

尝试 #3: Monkeypatching Dispatch

重写我们的dispatch

let next = store.dispatch

store.dispatch = function dispatchAndLog(action) {

  console.log('dispatching', action)

  // 调用原来的 dispatch

  let result = next(action)

  console.log('next state', store.getState())

  return result

}

 

问题: 崩溃报告

按照如上想法,我们添加崩溃报告的处理

function patchStoreToAddLogging(store) {

  let next = store.dispatch

  store.dispatch = function dispatchAndLog(action) {

    console.log('dispatching', action)

    let result = next(action)

    console.log('next state', store.getState())

    return result

  }

}

 

function patchStoreToAddCrashReporting(store) {

  let next = store.dispatch

  store.dispatch = function dispatchAndReportErrors(action) {

    try {

      return next(action)

    } catch (err) {

      console.error('捕获一个异常!', err)

      Raven.captureException(err, {

        extra: {

          action,

          state: store.getState()

        }

      })

      throw err

    }

  }}

 

尝试 #4: 隐藏 Monkeypatching

现在我们不直接更改store.dispatch,而是返回一个新的dispatch,此时我们可以称我们的方法为“中间件”

function logger(store) {

  let next = store.dispatch

 

  return function dispatchAndLog(action) {

    console.log('dispatching', action)

    let result = next(action)

    console.log('next state', store.getState())

    return result

  }

}

 

新建一个方法,叫做“应用中间件”,接收 store 和 中间件数组

function applyMiddlewareByMonkeypatching(store, middlewares) {

  middlewares = middlewares.slice()

  middlewares.reverse()

 

  // 在每一个 middleware 中变换 dispatch 方法。

  middlewares.forEach(middleware =>

    // 调用中间件,每个中间件都返回一个新的dispatch

    store.dispatch = middleware(store)

  )

}

 

然后像这样应用多个 middleware:

applyMiddlewareByMonkeypatching(store, [ logger, crashReporter ])

 

尝试 #5: 移除 Monkeypatching

ES6 的箭头函数可以使其 柯里化 ,从而看起来更舒服一些:

const logger = store => next => action => {

  console.log('dispatching', action)

  let result = next(action)

  console.log('next state', store.getState())

  return result

}

 

const crashReporter = store => next => action => {

  try {

    return next(action)

  } catch (err) {

    console.error('Caught an exception!', err)

    Raven.captureException(err, {

      extra: {

        action,

        state: store.getState()

      }

    })

    throw err

  }

}

这正是 Redux middleware 的样子。

Middleware 接收了一个参数 next 其本身是 dispatch 函数,并返回一个新的 dispatch 函数,返回的函数会被作为下一个 middleware 的 next()

不明白柯里化函数,如下,这样写应该会明白

store => next => action => {...}

store => {

    return (next => {

        return (action => {

            ...

        })

    })

}

 

尝试 #6: “单纯”地使用 Middleware

写一个 applyMiddleware 方法替换原来的 applyMiddlewareByMonkeypatching

// 警告:这只是一种“单纯”的实现方式!// 这 *并不是* Redux 的 API.

function applyMiddleware(store, middlewares) {

  middlewares = middlewares.slice()

  middlewares.reverse()

 

  let dispatch = store.dispatch

  middlewares.forEach(middleware =>

    dispatch = middleware(store)(dispatch)

  )

 

  return Object.assign({}, store, { dispatch })

}

这与 Redux 中 applyMiddleware() 的实现已经很接近了

 

使用Redux的applyMiddleware

Redux的applyMiddleware原理就是我们所编写的applyMiddleware

import { createStore, combineReducers, applyMiddleware } from 'redux'

let todoApp = combineReducers(reducers)

let store = createStore(

  todoApp,

  // applyMiddleware() 告诉 createStore() 如何处理中间件

  applyMiddleware(logger, crashReporter))

 

就是这样!现在任何被发送到 store 的 action 都会经过 logger 和 crashReporter

// 将经过 logger 和 crashReporter 两个 middleware!

store.dispatch(addTodo('Use Redux'))

需求响应动态冰蓄冷系统与需求响应策略的优化研究(Matlab代码实现)内容概要:本文围绕需求响应动态冰蓄冷系统及其优化策略展开研究,结合Matlab代码实现,探讨了在电力需求侧管理背景下,冰蓄冷系统如何通过优化运行策略参与需求响应,以实现削峰填谷、降低用电成本和提升能源利用效率的目标。研究内容包括系统建模、负荷预测、优化算法设计(如智能优化算法)以及多场景仿真验证,重点分析不同需求响应机制下系统的经济性和运行特性,并通过Matlab编程实现模型求解与结果可视化,为实际工程应用提供理论支持和技术路径。; 适合人群:具备一定电力系统、能源工程或自动化背景的研究生、科研人员及从事综合能源系统优化工作的工程师;熟悉Matlab编程且对需求响应、储能优化等领域感兴趣的技术人员。; 使用场景及目标:①用于高校科研中关于冰蓄冷系统与需求响应协同优化的课题研究;②支撑企业开展楼宇能源管理系统、智慧园区调度平台的设计与仿真;③为政策制定者评估需求响应措施的有效性提供量化分析工具。; 阅读建议:建议读者结合文中Matlab代码逐段理解模型构建与算法实现过程,重点关注目标函数设定、约束条件处理及优化结果分析部分,同时可拓展应用其他智能算法进行对比实验,加深对系统优化机制的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值