首页
学习
活动
专区
圈层
工具
发布

确定性API调用导致redux存储

确定性API调用与Redux存储问题解析

基础概念

确定性API调用

确定性API调用指的是在相同输入条件下总是产生相同输出的API请求。这类调用通常不依赖外部状态或时间因素,结果可预测且可重复。

Redux存储

Redux是一个用于JavaScript应用的状态管理库,它使用单一的不可变状态树来存储整个应用的状态,并通过纯函数(reducers)来修改状态。

问题分析

当确定性API调用与Redux存储结合使用时,可能会遇到以下问题:

  1. 不必要的重复请求:即使API响应相同,Redux可能仍然触发重新渲染
  2. 缓存失效:确定性API结果没有被有效缓存
  3. 状态同步问题:API响应与Redux存储状态不一致

原因

  1. 缺乏请求去重机制:相同的API调用被多次dispatch
  2. 缺少响应缓存:相同的响应数据被多次处理
  3. 副作用管理不当:Redux中间件未正确处理API调用的确定性

解决方案

1. 使用请求去重

代码语言:txt
复制
// 使用redux-thunk中间件实现请求去重
const fetchSomeData = (params) => {
  return async (dispatch, getState) => {
    const { data } = getState();
    const cacheKey = JSON.stringify(params);
    
    // 检查是否已有相同请求在进行中
    if (data.pendingRequests.includes(cacheKey)) {
      return;
    }
    
    // 标记请求为进行中
    dispatch({ type: 'REQUEST_STARTED', payload: cacheKey });
    
    try {
      const response = await api.fetchData(params);
      dispatch({ type: 'REQUEST_SUCCESS', payload: { cacheKey, data: response } });
    } catch (error) {
      dispatch({ type: 'REQUEST_FAILED', payload: { cacheKey, error } });
    }
  };
};

2. 实现响应缓存

代码语言:txt
复制
// reducer中实现缓存逻辑
const dataReducer = (state = { cache: {}, pendingRequests: [] }, action) => {
  switch (action.type) {
    case 'REQUEST_STARTED':
      return {
        ...state,
        pendingRequests: [...state.pendingRequests, action.payload]
      };
    case 'REQUEST_SUCCESS':
      return {
        ...state,
        cache: {
          ...state.cache,
          [action.payload.cacheKey]: action.payload.data
        },
        pendingRequests: state.pendingRequests.filter(
          key => key !== action.payload.cacheKey
        )
      };
    case 'REQUEST_FAILED':
      return {
        ...state,
        pendingRequests: state.pendingRequests.filter(
          key => key !== action.payload.cacheKey
        )
      };
    default:
      return state;
  }
};

3. 使用Redux中间件优化

代码语言:txt
复制
// 自定义中间件处理确定性API调用
const deterministicApiMiddleware = store => next => action => {
  if (action.type === 'API_CALL' && action.meta?.deterministic) {
    const state = store.getState();
    const cacheKey = action.meta.cacheKey || JSON.stringify(action.payload);
    
    // 检查缓存
    if (state.apiCache[cacheKey]) {
      return next({
        type: 'API_CACHE_HIT',
        payload: state.apiCache[cacheKey],
        meta: { cacheKey }
      });
    }
    
    // 标记为进行中
    next({
      type: 'API_CALL_STARTED',
      meta: { cacheKey }
    });
    
    // 实际API调用
    return apiCall(action.payload)
      .then(response => {
        return next({
          type: 'API_CALL_SUCCESS',
          payload: response,
          meta: { cacheKey, deterministic: true }
        });
      })
      .catch(error => {
        return next({
          type: 'API_CALL_FAILED',
          payload: error,
          meta: { cacheKey }
        });
      });
  }
  
  return next(action);
};

最佳实践

  1. 为确定性API调用添加标记:在action中明确标记是否为确定性调用
  2. 使用标准化缓存键:确保相同参数的请求能命中相同缓存
  3. 考虑缓存过期策略:即使是确定性API,有时也需要刷新数据
  4. 优化组件渲染:使用React.memo或useMemo避免不必要的重新渲染

应用场景

  1. 配置信息获取
  2. 静态数据加载
  3. 权限检查
  4. 国际化资源加载
  5. 任何不频繁变化的后端数据

通过以上方法,可以有效解决确定性API调用与Redux存储结合时产生的问题,提高应用性能和用户体验。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Uber服务端响应中的API调用缺陷导致的账户劫持

今天分享的writeup是中国香港白帽Ron Chan (@ngalongc)发现的一个关于Uber网站的漏洞,他通过分析Uber的微服务架构和其中的API调用机制,利用其中的服务端响应缺陷,能以...Uber的Web应用服务体系是基于很多微服务架构部署的,由于微服务中会涉及到大量的REST模式,因此,在与各种Uber应用的交互过程中,Uber服务端难免会调用到一些REST API接口。...所以,矛盾点来了,如果这类API调用都是以预定的path/variables/host方式进行的,而且,这些调用是用户无法控制的,那么,Web应用后端(Backend)设置的身份验证措施又有何用呢?...用户确实不能控制这类API调用吗?我觉得这里要打个问号。...earnings_structure_type=&locale=en&user_id=xxxx 这是一个典型的后端REST API调用。

1.6K10

PHP调用Github API结合jsdelivr作对象存储(文件转链接)

对于偌大的一个群来说确实能防止很多问题,不过有时也略显不方便,因此感觉自己发现了商机开发了一个这样的网页,也可以将其作为方便的对象存储使用。...相信大家都知道Github这个平台,人人都可以在其中建立repo,且没有限制大小,相当于一个 免费的对象存储 了,不过由于服务器的位置问题, 速度还是比较慢 。...由此便产生了使用 php+Github+jsdelivr 进行开发的想法 具体的思路 首先需要解决的是 php调用Github API 的问题。...php基本一窍不通,但是毕竟学过一些基础的编程,于是上来就找了一番Github官方的文档: https://developer.github.com/v3/guides/ ,此外我还对照参考了 其他语言 调用...Github API上传文件的一些代码资料。

1.2K21
  • JavaScript 中的函数式编程:纯函数与副作用

    函数式编程概述函数式编程是一种编程范式,它将计算视为数学函数的求值,强调函数的无状态性、确定性和不可变性。...纯函数具有以下几个关键特性:确定性:对于相同的输入,总是返回相同的输出。这意味着纯函数的结果仅取决于其输入参数,不受外部变量、状态或其他不可控因素的影响。...console.log(increment()); // 输出: 1console.log(increment()); // 输出: 2increment 函数具有副作用,因为它修改了全局变量 counter,导致每次调用时返回的结果不同...addPure 对于相同的输入总是返回相同的输出,而 addWithSideEffect 修改了全局变量 total,导致每次调用时返回的结果不同。...纯函数提供了确定性和无副作用的特性,使得代码更易于理解和维护。副作用虽然不可避免,但我们可以通过合理的设计和管理来控制其影响。

    41100

    Top JavaScript Frameworks & Topics to Learn in 2017

    作者: Eric Elliott 译:Adamhe 原文: 《Top JavaScript Frameworks & Topics to Learn in 2017》 JavaScript 的普及导致了一个非常活跃的技术...calls (Ajax和服务器API调用): 那些最好玩的应用程序最终需要与网络通信。...Yarn*: 类似于 npm,但安装行为是确定性的,Yarn的目标是比 npm 快。 TypeScript*: avaScript的静态类型。完全可选,除非你学习Angular 2。...使用双向绑定,在 DOM 渲染过程(称为 Angular 1中的摘要循环)中对 DOM的 更改可能会在绘制完成之前重新触发绘图阶段,从而导致回流和重绘 - 从而降低性能。...Redux Redux 为您的应用程序提供事务性,确定性状态管理。在 Redux 中,我们遍历操作对象流以减少到当前应用程序状态。

    2.8K00

    精读《重新思考 Redux》

    简化初始化 redux 初始化代码涉及的概念比较多,比如 compose thunk 等等,同时将 reducer、initialState、middlewares 这三个重要概念拆分成了函数方式调用,...{}, reducers: { count }, middlewares: [api, devTools] }); 笔者注:redux 的初始化方式非常函数式,而下面的配置方式就更面向对象一些...简化 Reducers redux 的 reducer 粒度太大,不但导致函数内手动匹配 type,还带来了 type、payload 等理解成本: const countReducer = (state...不再显示申明 action type 不要在用一个文件存储 Action 类型了,const ACTION_ONE = 'ACTION_ONE' 其实重复写了一遍字符串,直接用对象的 key 表示 action...Reducer 直接作为 ActionCreator redux 调用 action 比较繁琐,使用 dispatch 或者将 reducer 经过 ActionCreator 函数包装。

    56020

    【干货】2017年值得关注的JavaScript框架与主题

    Callbacks: 回调是JavaScript异步编程的基本概念,某个回调函数会在某个异步操作结束后被调用,就好比领导对你说:好好干你的工作,做好了跟我汇报下。...Promises: Promise是处理将来值的方法之一,当某个函数返回的是Promise对象时,你可以调用该对象的then函数来获取异步传入的值。...而调用者是通过传入的resolve回调来传值,譬如doSomething().then(value => console.log(value)); Ajax & 服务端API调用: 绝大部分有趣的应用都需要与服务端通过网络进行交互...这种单向数据流与当时以Angular 1 / Knockout为代表的双向数据绑定形成对比,双向数据绑定中如果发现绑定的数据发生变化则会立刻触发重渲染,而无论当前是否处于渲染流程中,这一点也就导致了Reflows...Redux Redux 为应用提供了事务式的,确定性的状态管理支持。在Redux中,我们仅可以通过Action来修改当前的应用状态。

    1.5K60

    前端高频react面试题

    那为什么不要在循环、条件或嵌套函数中调用 Hook 呢?因为 Hooks 的设计是基于数组实现。在调用时按顺序加入数组中,如果使用循环、条件或嵌套函数很有可能导致数组取值错位,执行错误的 Hook。...这个问题就设计到了数据持久化, 主要的实现方式有以下几种:Redux: 将页面的数据存储在redux中,在重新加载页面时,获取Redux中的数据;data.js: 使用webpack构建的项目,可以建一个文件...返回或进入除了选择地址以外的页面,清掉存储的sessionStorage,保证下次进入是初始化的数据history API: History API 的 pushState 函数可以给历史记录关联一个任意的可序列化...这个方法适合一些需要临时存储的场景。Redux 中异步的请求怎么处理可以在 componentDidmount 中直接进⾏请求⽆须借助redux。...个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是rxjs

    4K20

    Redux源码浅析

    flag是标记当前正在执行reducer,reducer是用户写的,这个flag是为了不让用户在reducer方法中执行其他可能会破环正常数据流程的方法,比如在reducer中再次dispatch,会导致死循环...4. bindActionCreators在使用react-redux写mapDispatchToProps经常会使用bindActionCreators这个API,如下图图片这个API可以在子组件dispatch...对外导出的bindActionCreators API可以接受多个actionCreators(即集合),然后以key-value的形式调用bindActionCreator并保存结果返回。...Redux本身并不包括中间件代码,只是支持应用按照规范写的中间件,或使用现成中间件(如redux-thunk)。应用中间件的API为applyMiddleware。...applyMiddleware的函数内容为:调用参数传入的createStore方法,创建store;封装一个middlewareAPI作为store传参给middleware(该API并非真正的store

    1.8K71

    在线商城库存实时更新引发页面冻结:Redux Toolkit 异步困境与紧急修复

    :高频次的状态更新:库存信息更新频率过高(每秒多次),导致 Redux 状态频繁变更。...,减少不必要的重渲染使用 Web Worker 处理复杂计算,避免阻塞主线程4.1 优化 Redux 状态结构原有的库存状态使用数组存储,每次更新需要遍历查找,效率低下。...调用逻辑......该问题的根本原因是高频次的 Redux 状态更新、低效的状态处理逻辑以及不合理的组件渲染机制共同导致的主线程阻塞。...从这个问题的排查和解决过程中,我获得了以下宝贵经验:状态设计至关重要:合理的 Redux 状态结构能显著提升性能,特别是对于频繁更新的数据,应优先考虑使用对象而非数组存储,以提高查找和更新效率。

    20020

    2022社招React面试题 附答案

    ,将渲染逻辑交给调用者。...这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿。 为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。...Reducer,并且传入两个参数:当前State和收到的Action,Reducer会返回新的State State—旦有变化,Store就会调用监听函数,来更新View 以 store 为核心,可以把它看成数据存储中心...,⽽且有数⼗个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是...Redux 状态管理器和变量挂载到 window 中有什么区别 两者都是存储数据以供后期使用。

    2.4K50

    2021高频前端面试题汇总之React篇

    ,将渲染逻辑交给调用者。...这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿。 为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。...Reducer,并且传入两个参数:当前State和收到的Action,Reducer会返回新的State State—旦有变化,Store就会调用监听函数,来更新View 以 store 为核心,可以把它看成数据存储中心...,⽽且有数⼗个API,学习成本远超redux-thunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是...Redux 状态管理器和变量挂载到 window 中有什么区别 两者都是存储数据以供后期使用。

    2.5K00

    react高频面试题总结(附答案)

    如果将 setState 写在条件判断中,假设条件判断不成立,没有执行里面的 setState 方法,会导致接下来所有的 setState 的取值出现偏移,从而导致异常发生。父子组件的通信方式?...存储全局数据时,会有一个问题,如果用户刷新了网页,那么通过redux存储的全局数据就会被全部清空,比如登录信息等。...这时就会有全局数据持久化存储的需求。首先想到的就是localStorage,localStorage是没有时间限制的数据存储,可以通过它来实现数据的持久化存储。...但是在已经使用redux来管理和存储全局数据的基础上,再去使用localStorage来读写数据,这样不仅是工作量巨大,还容易出错。那么有没有结合redux来达到持久数据存储功能的框架呢?...这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿。为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。

    2.7K40

    React-全局状态管理的群魔乱舞

    ❞ 写入存储状态的能力 一个库应该提供一个直观的API来读取和写入存储的数据。 一个直观的API应该是符合人们现有心智模式的。很多时候,心智模式的冲突会导致使用该库的学习和应用曲线陡增。...--《间谍过家家》 虽然Redux仍然是一个伟大的状态管理库,对特定的应用程序有真正的用处。随着时间的推移,Redux 在一些特定的领域,变现不尽人意,导致它不再受到青睐。...随着应用程序的发展,Redux 倾向于「吸纳所有的状态」,不管它是什么类型,因为它提倡单一的存储。 这通常会「导致将所有的东西存储在一个大的单体存储中」。...从子树的任何地方读取存储状态 库 更新时机 API示例 React-Redux 嵌入到React运行时 useSelector(state => state.foo) Recoil 嵌入到React运行时...库 描述 React-Redux 「手动」管理 Recoil 0.3.0版本后- 「自动」管理 Jotai 「自动」管理 - atoms作为键存储在WeakMap中 Zustand 「半自动」--API

    4.2K20

    2023再谈前端状态管理

    缺点 Context 只能存储单一值,当数据量大起来时,你可能需要使用createContext创建大量context; 直接使用的话,会有一定的性能问题:每一次对state的某个值变更,都会导致其他使用该...Class 时代 Redux Redux 的灵感来源于 Flux 架构和函数式编程原理,状态更新可预测、可跟踪,提倡使用「单一存储」。这通常会「导致将所有的东西存储在一个大的单体存储中」。...将副作用扔给中间件来处理,导致社区一堆中间件,学习成本陡然增加。比如处理异步请求的 Redux-saga、计算衍生状态的 reselect; 大量的模版代码。...每个 action 都会调用所有 reducer; reducer 要返回新的对象,如果更新的值层级较深,更新成本也很高; 更多的内存占用,由于采用单一数据源,所有状态存储在一个 state 中,当某些状态不再需要使用时...代数效应是函数式编程中的一个概念,用于将副作用从函数调用中分离。 自下而上模式的崛起 我们可以看到以前的状态管理解决方案,如Redux,设计理念是状态 「自上而下」流动。

    1.4K10

    2023前端二面react面试题(边面边更)

    StrictMode 目前有助于:识别不安全的生命周期关于使用过时字符串 ref API 的警告关于使用废弃的 findDOMNode 方法的警告检测意外的副作用检测过时的 context APIhooks...存储全局数据时,会有一个问题,如果用户刷新了网页,那么通过redux存储的全局数据就会被全部清空,比如登录信息等。...这时就会有全局数据持久化存储的需求。首先想到的就是localStorage,localStorage是没有时间限制的数据存储,可以通过它来实现数据的持久化存储。...但是在已经使用redux来管理和存储全局数据的基础上,再去使用localStorage来读写数据,这样不仅是工作量巨大,还容易出错。那么有没有结合redux来达到持久数据存储功能的框架呢?...工厂组件会导致 React 变大且变慢。act()也支持异步函数,并且你可以在调用它时使用 await。使用 进行性能评估。

    2.9K50

    Taro 小程序开发大型实战(六):尝鲜微信小程序云(上篇)

    存储:支持文本、图片等用户生成内容的存储,可以获取资源的链接进行使用。...云函数:可以用 Node.js 进行开发,自己编写对应的后端逻辑,并把写好的代码传到云端,然后在小程序前端使用 API 进行调用。...序号4是代表我们此次的云环境的标识符,可以用于在小程序端以 API 调用云开发资源时标志此时的调用的云环境。 在本篇教程中,我们会用到上面提到的数据库和云函数两项功能。...在 try 语句中,首先是使用了 redux-saga 提供给我们的 effects helper 函数:call 来调用登录的 API:userApi.login,并把 userInfo 作为参数传给这个...的方式来调用 login API 处理登录逻辑了。

    2.6K20
    领券