我正在使用Reselect为React + Redux创建各种选择器。当我有超过100万个项目时,我会遇到性能问题,选择器的计算可能会花费300毫秒至500毫秒,因为它必须使用昂贵的检查功能对所有项目进行过滤和排序。
我是normalizing的州,在Redux中,我将项目存储在byIds
中,并将id存储在allIds
中。一切都很好。但是,当我添加新项时,byIds
和allIds
将被更新,这意味着选择器将不得不再次重新计算所有1M项,而不仅仅是计算新项。
是否有一些聪明的方法可以解决此问题,或者我缺少什么。以前我没有使用任何选择器。这意味着我在将所有新项目添加到商店之前对其进行了过滤,但这带来了我的数据不纯净的副作用。
我考虑过的一些方法是重新构造数据或为数据创建某种层次,以便更好地记住部分数据。
这是我的选择器的结构:
postsIds
,其中包含所有项目的ID并对其进行过滤。例如。阻止或错误类型的项目应被过滤掉。getVisiblePostsIds
并按条件对项目进行排序getSortedPostsIds
并在项目过多的情况下切片item数组。如果可能的话,这里是粗糙的源代码。
const getVisiblePostsIds = createSelector(
[
getFeedsByIds,
getPostsIds,
getPostsByIds,
getFeedType,
getStartDate,
getModerationDict,
],
(
feedsByIds,
postsIds,
postsByIds,
feedType,
startTime,
moderationDict,
) => {
return postsIds.filter(
postId =>
postsByIds[postId].created >= startTime
&& feedsByIds[postsByIds[postId].feedId].IgnoreStartDate === false
&& moderationDict[postsByIds[postId].mediaId] === undefined
&& moderationDict[postsByIds[postId].userId] === undefined
&& (feedType === FEED_TYPE.SHOW_BOTH
|| (feedType === FEED_TYPE.SHOW_MEDIA_FEED_ONLY && postsByIds[postId].type > 1)
|| (feedType === FEED_TYPE.SHOW_TEXT_FEED_ONLY && postsByIds[postId].type === POST_TYPE.TEXT)),
)
},
)
const getSortedPostsIds = createSelector(
[
getSlideArrangement,
getVisiblePostsIds,
getPostsByIds,
],
(
slideArrangement,
postsIds,
postsByIds,
// .slice() is supposed to be faster than [...postIds] to clone the array without mutation
) => postsIds.slice().sort(comparePosts(postsByIds, slideArrangement)),
)
export const getFilteredPostsIds = createSelector(
[
getSortedPostsIds,
getHasLoopLimit,
getLoopLimit,
getSlideArrangement,
],
(
postsIds,
hasLoopLimit,
loopLimit,
slideArrangement,
) => {
...array slice
},
)
谢谢。