From 5d0aae283f76fa73fbb32174d0d09471cd020c4a Mon Sep 17 00:00:00 2001 From: Brock Whittaker Date: Tue, 24 Oct 2017 16:03:43 -0700 Subject: [PATCH] input-pill: Add key/value caching. Some of the calls in our codebase will call for the `.keys()` method a lot, so this caches the results and returns them rather than mapping the array if it knows the state to be the same as before. --- static/js/input_pill.js | 47 ++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/static/js/input_pill.js b/static/js/input_pill.js index 55ecc7015d..0dc3d9809a 100644 --- a/static/js/input_pill.js +++ b/static/js/input_pill.js @@ -14,6 +14,11 @@ var input_pill = function ($parent) { pills: [], $parent: $parent, getKeyFunction: function () {}, + lastUpdated: null, + lastCreated: { + keys: null, + values: null, + }, }; // a dictionary of internal functions. Some of these are exposed as well, @@ -83,6 +88,7 @@ var input_pill = function ($parent) { // the jQuery element representation of the data. createPillElement: function (payload) { + store.lastUpdated = new Date(); payload.$element = $("
" + payload.value + "
×
"); return payload.$element; }, @@ -126,6 +132,7 @@ var input_pill = function ($parent) { if (typeof idx === "number") { store.pills[idx].$element.remove(); + store.lastUpdated = new Date(); return store.pills.splice(idx, 1); } }, @@ -134,6 +141,7 @@ var input_pill = function ($parent) { // to the "backspace" key when the value of the input is empty. removeLastPill: function () { var pill = store.pills.pop(); + store.lastUpdated = new Date(); if (pill) { pill.$element.remove(); @@ -151,17 +159,40 @@ var input_pill = function ($parent) { }, // returns all hidden keys. - keys: function () { - return store.pills.map(function (pill) { - return pill.key; - }); - }, + // IMPORTANT: this has a caching mechanism built in to check whether the + // store has changed since the keys/values were last retrieved so that + // if there are many successive pulls, it doesn't have to map and create + // an array every time. + // this would normally be a micro-optimization, but our codebase's + // typeaheads will ask for the keys possibly hundreds or thousands of + // times, so this saves a lot of time. + keys: (function () { + var keys = []; + return function () { + if (store.lastUpdated >= store.lastCreated.keys) { + keys = store.pills.map(function (pill) { + return pill.key; + }); + store.lastCreated.keys = new Date(); + } + + return keys; + }; + }()), // returns all human-readable values. values: function () { - return store.pills.map(function (pill) { - return pill.value; - }); + var values = []; + return function () { + if (store.lastUpdated >= store.lastCreated.values) { + values = store.pills.map(function (pill) { + return pill.value; + }); + store.lastCreated.values = new Date(); + } + + return values; + }; }, };