7

假设我正在 Redux 中编写一个应用程序,并且我的任务是使用 3rd 方库添加日志记录。它的API如下:

function createLogger(token) {
    // the logger has internal state!
    let logCount = 0;

    return {
        log(payload) {
            logCount++;            // modify local state

            fetch('/someapi', {    // ship payload to some API
                method: 'POST',
                body: payload
            });
        }
    };
}

然后我会使用这样的库:

let logger = createLogger('xyz');
logger.log('foobar');

我绝对想在应用程序初始化期间只创建一次记录器实例。但接下来的问题是:我在哪里存储记录器实例

首先是把它放在商店的某个地方。但这是个好主意吗?正如我在代码中所展示的,记录器对象是有状态的,它在闭包中存储了一个计数器。我没有像使用不可变对象那样获得新实例。众所周知,状态只能通过纯 reducer 函数进行修改。

其他可能性是在 redux 中间件闭包的某个地方创建实例,或者只是创建一个全局变量,这在可测试性方面显然是邪恶的。

对于这种(我认为)相当常见的情况,是否有最佳实践?

4

2 回答 2

4

由于您使用的是 ES6 模块,我会将您的记录器设置为模块,export它以及import您计划使用它的任何位置。我认为从动作中记录是一个可靠的计划,因为它使组件不知道,并且不会因副作用而污染商店。

function createLogger(token) {
    // the logger has internal state!
    let logCount = 0;

    return {
        log(payload) {
            logCount++;            // modify local state

            fetch('/someapi', {    // ship payload to some API
                method: 'POST',
                body: payload
            });
        }
    };
}

export default const logger = createLogger('xyz');

您的动作创建者

import logger from 'logger-module';

//
logger.log('somestuff');

通过导入记录器并在您需要拦截的方法上放置任何间谍/存根,仍然可以轻松实现测试。

于 2015-12-08T21:30:00.157 回答
0

Redux 文档

/**
 * Sends crash reports as state is updated and listeners are notified.
 */
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
  }
}

Raven作为第三方库。

如果库有自己的状态,那么在中间件中使用它应该不是问题(状态属于库而不是您的应用程序)。如果您出于某种原因为它创建一个状态,那么该状态应该属于 Redux 存储,可能在 store.logger 或其他东西下。

于 2015-12-10T16:55:07.320 回答