当前位置:网站首页>NgRx Selector 的 Memoization 特性学习笔记
NgRx Selector 的 Memoization 特性学习笔记
2022-08-01 21:54:00 【华为云】
在计算机编程领域中,memoization 或 memoisation 是一种优化技术,主要用于通过存储昂贵的函数调用的结果并在再次出现相同的输入时返回缓存的结果来加速计算机程序。
Memoization 也已用于其他上下文(以及速度增益以外的目的),例如在简单的相互递归下降解析中。尽管与缓存有关,但记忆化是指此优化的特定情况,将其与缓存或页面替换等缓存形式区分开来。在某些逻辑编程语言的上下文中,记忆化也称为 Tabling.
记忆功能“记住”与某些特定输入集相对应的结果。使用记住输入的后续调用返回记住的结果而不是重新计算它,从而消除了使用给定参数调用的主要成本,除了第一次使用这些参数调用函数。记住的关联集可以是由替换算法控制的固定大小的集,也可以是固定集,这取决于函数的性质及其用途。一个函数只有在引用透明的情况下才能被记忆;也就是说,仅当调用该函数与用其返回值替换该函数调用具有完全相同的效果时。 (然而,存在此限制的特殊情况例外。)虽然与查找表相关,但由于记忆在其实现中经常使用此类表,因此记忆会根据需要即时而不是提前填充其结果缓存。
记忆化是一种以牺牲空间成本的方法来降低函数时间成本的优化方式;也就是说,记忆化的函数会针对速度进行优化,付出的代价是对计算机内存空间的更高使用率。算法的时间/空间“成本”在计算中有一个特定的名称:计算复杂度。所有函数在时间(即它们需要时间来执行)和空间上都具有计算复杂性。
什么是 NgRx selector
选择器是用于获取存储状态切片( store state slices)的纯函数。@ngrx/store 提供了一些帮助函数来优化这个选择。
Selector 也符合单一职责及 Single responsibility,一个 selector 只 touch State 的一个片段。
使用 createSelector 和 createFeatureSelector 函数时,@ngrx/store 会跟踪调用选择器函数的最新参数。 因为选择器是纯函数,当参数匹配时可以返回最后一个结果,而无需重新调用选择器函数。这可以提供性能优势,特别是对于执行昂贵计算的选择器。这种做法被称为记忆。
换言之,我们虽然实现了 Selector,但是运行时,这些 selector 可能只会被执行一次,因为如果输入参数相同,NgRx 框架会使用缓存的结果直接返回给调用者,而不会重复调用我们的 Selector.
例子:Using a selector for one piece of state
import { createSelector } from '@ngrx/store';export interface FeatureState { counter: number;}export interface AppState { feature: FeatureState;}export const selectFeature = (state: AppState) => state.feature;export const selectFeatureCount = createSelector( selectFeature, (state: FeatureState) => state.counter);console.log('ok');
例子:Using selectors for multiple pieces of state
createSelector 可用于基于相同状态(State)的多个切片从状态中选择一些数据。
createSelector 函数最多可以使用 8 个选择器函数,用于更完整的状态选择。
例如,假设您在状态中有一个 selectedUser 对象。 您还有一个 allBooks 书籍对象数组。
并且您想显示当前用户的所有书籍。
您可以使用 createSelector 来实现这一点。即使您在 allBooks 中更新它们,您的可见书籍也将始终是最新的。 如果选择了一个,它们将始终显示属于您的用户的书籍,如果没有选择用户,它们将显示所有书籍。
CreateSelector 里传入纯函数。
import { createSelector } from '@ngrx/store';export interface User { id: number; name: string;}export interface Book { id: number; userId: number; name: string;}export interface AppState { selectedUser: User; allBooks: Book[];}export const selectUser = (state: AppState) => state.selectedUser;export const selectAllBooks = (state: AppState) => state.allBooks;export const selectVisibleBooks = createSelector( selectUser, selectAllBooks, (selectedUser: User, allBooks: Book[]) => { if (selectedUser && allBooks) { return allBooks.filter((book: Book) => book.userId === selectedUser.id); } else { return allBooks; } });
Selecting Feature States
createFeatureSelector 是返回顶级功能状态(Top Level Feature State)的便捷方法。它为状态的特征切片返回一个类型化的选择器函数。
import { createSelector, createFeatureSelector } from '@ngrx/store';export const featureKey = 'feature';export interface FeatureState { counter: number;}export interface AppState { feature: FeatureState;}export const selectFeature = createFeatureSelector<AppState, FeatureState>(featureKey);export const selectFeatureCount = createSelector( selectFeature, (state: FeatureState) => state.counter);
Resetting Memoized Selectors
通过调用 createSelector 或 createFeatureSelector 返回的选择器函数最初的记忆值为 null。 在第一次调用选择器后,其记忆值存储在内存中。 如果随后使用相同的参数调用选择器,它将返回记忆值。 如果随后使用不同的参数调用选择器,它将重新计算并更新其记忆值。
一个例子:
import { createSelector } from '@ngrx/store';export interface State { counter1: number; counter2: number;}export const selectCounter1 = (state: State) => state.counter1;export const selectCounter2 = (state: State) => state.counter2;export const selectTotal = createSelector( selectCounter1, selectCounter2, (counter1, counter2) => counter1 + counter2); // selectTotal has a memoized value of null, because it has not yet been invoked.let state = { counter1: 3, counter2: 4 };selectTotal(state); // computes the sum of 3 & 4, returning 7. selectTotal now has a memoized value of 7selectTotal(state); // does not compute the sum of 3 & 4. selectTotal instead returns the memoized value of 7state = { ...state, counter2: 5 };selectTotal(state); // computes the sum of 3 & 5, returning 8. selectTotal now has a memoized value of 8
选择器的记忆值无限期地保留在内存中。 例如,如果记忆值是不再需要的大数据集,则可以将记忆值重置为 null,以便可以从内存中删除大数据集。 这可以通过调用选择器上的 release 方法来完成。
selectTotal(state); // returns the memoized value of 8selectTotal.release(); // memoized value of selectTotal is now null
边栏推荐
- 365 days challenge LeetCode1000 questions - Day 046 Generate a string with odd number of each character + add two numbers + valid parentheses
- 模拟数据之mockjs
- 找工作必备!如何让面试官对你刮目相看,建议收藏尝试!!
- 毕业十年,财富自由:那些比拼命努力更重要的事,从来没人会教你
- (*゚ヮ゚)*【精品C语言整理】*(゚ヮ゚*)女盆友缠着你让你教她写代码怎么办?安排,三万字博文带你走遍C语言,从此不再害怕编程
- 还在纠结报表工具的选型么?来看看这个
- 递归(各经典例题分析)
- seaborn笔记:可视化统计关系(散点图、折线图)
- 安全第五次课后练习
- [Mobile Web] Mobile terminal adaptation
猜你喜欢
宝塔应用使用心得
Uses of Anacoda
图像融合GANMcC学习笔记
找工作必备!如何让面试官对你刮目相看,建议收藏尝试!!
FusionGAN:A generative adversarial network for infrared and visible image fusion文章学习笔记
10 Practical Uses of NFTs (NFT System Development)
Kubernetes第零篇:认识kubernetes
SOM网络1:原理讲解
迁移学习——Discriminative Transfer Subspace Learning via Low-Rank and Sparse Representation
Unity Shader 常规光照模型代码整理
随机推荐
小程序中的多表联合查询
Spark practice questions + answers
10 Practical Uses of NFTs (NFT System Development)
19 Lectures on Disassembly of Multi-merchant Mall System Functions - Invoice Management on the Platform
Spark shuffle tuning
SOM Network 1: Principles Explained
使用分类权重解决数据不平衡的问题
入门数据库Days4
MySQL相关知识
论文解读(GSAT)《Interpretable and Generalizable Graph Learning via Stochastic Attention Mechanism》
恒星的正方形问题
2022 edition of MySQL tutorial, top collection good, take your time
render-props和高阶组件
Pagoda application experience
ImportError: `save_weights` requires h5py.问题解决
【C语言实现】两种计算平均成绩题型,博主精心整理,值得一读
Kubernetes第零篇:认识kubernetes
SOM Network 2: Implementation of the Code
高等代数_证明_矩阵的行列式为特征值之积, 矩阵的迹为特征值之和
Flink cluster construction