From 1c191a1f15c007e7f2a4d2ddc6797b6288202be9 Mon Sep 17 00:00:00 2001 From: chriddyp Date: Thu, 1 Feb 2018 15:01:03 -0500 Subject: [PATCH] fix initialization routines in initialization, we need to update all of the leaf inputs. sometimes, there are leaf inputs with overlapping outputs. previously, we would trigger an update for each input, which would then trigger an update for each of its outputs. now, we skip triggering updates to outputs if they have already been covered by a separate input. --- src/actions/index.js | 60 +++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/actions/index.js b/src/actions/index.js index 80a812e..54bb84a 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -8,6 +8,8 @@ import { contains, findIndex, findLastIndex, + flatten, + flip, has, intersection, isEmpty, @@ -16,6 +18,7 @@ import { merge, pluck, propEq, + reject, slice, sort, type, @@ -65,8 +68,8 @@ function triggerDefaultState(dispatch, getState) { } }); - reduceInputIds(inputNodeIds, InputGraph).forEach(nodeId => { - const [componentId, componentProp] = nodeId.split('.'); + reduceInputIds(inputNodeIds, InputGraph).forEach(inputOutput => { + const [componentId, componentProp] = inputOutput.input.split('.'); // Get the initial property const propLens = lensPath( concat(getState().paths[componentId], @@ -79,8 +82,10 @@ function triggerDefaultState(dispatch, getState) { dispatch(notifyObservers({ id: componentId, - props: {[componentProp]: propValue} + props: {[componentProp]: propValue}, + excludedOutputs: inputOutput.excludedOutputs })); + }); } @@ -136,7 +141,9 @@ function reduceInputIds(nodeIds, InputGraph) { */ const inputOutputPairs = nodeIds.map(nodeId => ({ input: nodeId, - outputs: InputGraph.dependenciesOf(nodeId) + // TODO - Does this include grandchildren? + outputs: InputGraph.dependenciesOf(nodeId), + excludedOutputs: [] })); const sortedInputOutputPairs = sort( @@ -144,12 +151,28 @@ function reduceInputIds(nodeIds, InputGraph) { inputOutputPairs ); - const uniquePairs = sortedInputOutputPairs.filter((pair, i) => !contains( - pair.outputs, - pluck('outputs', slice(i + 1, Infinity, sortedInputOutputPairs)) - )); + /* + * In some cases, we may have unique outputs but inputs that could + * trigger components to update multiple times. + * + * For example, [A, B] => C and [A, D] => E + * The unique inputs might be [A, B, D] but that is redudant. + * We only need to update B and D or just A. + * + * In these cases, we'll supply an additional list of outputs + * to exclude. + */ + sortedInputOutputPairs.forEach((pair, i) => { + const outputsThatWillBeUpdated = flatten(pluck( + 'outputs', slice(0, i, sortedInputOutputPairs))); + pair.outputs.forEach(output => { + if (contains(output, outputsThatWillBeUpdated)) { + pair.excludedOutputs.push(output); + } + }); + }); - return pluck('input', uniquePairs); + return sortedInputOutputPairs; } @@ -159,7 +182,8 @@ export function notifyObservers(payload) { const { id, event, - props + props, + excludedOutputs } = payload const { @@ -167,7 +191,6 @@ export function notifyObservers(payload) { requestQueue, } = getState(); const {EventGraph, InputGraph} = graphs; - /* * Figure out all of the output id's that depend on this * event or input. @@ -192,6 +215,13 @@ export function notifyObservers(payload) { }); } + if (excludedOutputs) { + outputObservers = reject( + flip(contains)(excludedOutputs), + outputObservers + ); + } + if (isEmpty(outputObservers)) { return; } @@ -630,11 +660,13 @@ function updateOutput( keys(newProps), InputGraph); const depOrder = InputGraph.overallOrder(); const sortedNewProps = sort((a, b) => - depOrder.indexOf(a) - depOrder.indexOf(b), + depOrder.indexOf(a.input) - depOrder.indexOf(b.input), reducedNodeIds ); - sortedNewProps.forEach(function(nodeId) { - dispatch(notifyObservers(newProps[nodeId])); + sortedNewProps.forEach(function(inputOutput) { + const payload = newProps[inputOutput.input]; + payload.excludedOutputs = inputOutput.excludedOutputs; + dispatch(notifyObservers(payload)); }); // Dispatch updates to lone outputs