Remove utilCallWhenIdle, use requestIdleCallback/cancelIdleCallback

Places where a reset or connection switch would be problematic,
we can now cancel the callbacks.
This commit is contained in:
Bryan Housel
2019-05-16 22:28:56 -04:00
parent a8c6ab4d67
commit bdb454e1b3
10 changed files with 69 additions and 65 deletions
+17 -7
View File
@@ -6,24 +6,24 @@ import { select as d3_select } from 'd3-selection';
import { t, currentLocale, addTranslation, setLocale } from '../util/locale';
import { osmSetAreaKeys, osmSetPointTags, osmSetVertexTags } from '../osm/tags';
import { coreHistory } from './history';
import { coreValidator } from './validator';
import { dataLocales, dataEn } from '../../data';
import { geoRawMercator } from '../geo/raw_mercator';
import { modeSelect } from '../modes/select';
import { osmSetAreaKeys, osmSetPointTags, osmSetVertexTags } from '../osm/tags';
import { presetIndex } from '../presets';
import { rendererBackground, rendererFeatures, rendererMap, rendererPhotos } from '../renderer';
import { services } from '../services';
import { uiInit } from '../ui/init';
import { utilDetect } from '../util/detect';
import { utilCallWhenIdle, utilKeybinding, utilRebind, utilStringQs } from '../util';
import { utilKeybinding, utilRebind, utilStringQs } from '../util';
export function coreContext() {
var dispatch = d3_dispatch('enter', 'exit', 'change');
var context = utilRebind({}, dispatch, 'on');
var _deferred = new Set();
context.version = '2.14.3';
@@ -135,21 +135,25 @@ export function coreContext() {
context.loadTiles = function(projection, callback) {
utilCallWhenIdle(function() {
var handle = window.requestIdleCallback(function() {
_deferred.delete(handle);
if (connection && context.editable()) {
var cid = connection.getConnectionId();
connection.loadTiles(projection, afterLoad(cid, callback));
}
})();
});
_deferred.add(handle);
};
context.loadTileAtLoc = function(loc, callback) {
utilCallWhenIdle(function() {
var handle = window.requestIdleCallback(function() {
_deferred.delete(handle);
if (connection && context.editable()) {
var cid = connection.getConnectionId();
connection.loadTileAtLoc(loc, afterLoad(cid, callback));
}
})();
});
_deferred.add(handle);
};
context.loadEntity = function(entityID, callback) {
@@ -454,6 +458,12 @@ export function coreContext() {
/* reset (aka flush) */
context.reset = context.flush = function() {
context.debouncedSave.cancel();
Array.from(_deferred).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred.delete(handle);
});
Object.values(services).forEach(function(service) {
if (service && typeof service.reset === 'function') {
service.reset(context);
+11 -5
View File
@@ -2,7 +2,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch';
import { coreDifference } from './difference';
import { modeSelect } from '../modes/select';
import { utilArrayGroupBy, utilCallWhenIdle, utilRebind } from '../util';
import { utilArrayGroupBy, utilRebind } from '../util';
import { t } from '../util/locale';
import { validationIssueFix } from './validation/models';
import * as Validations from '../validations/index';
@@ -19,7 +19,7 @@ export function coreValidator(context) {
var _issuesByIssueID = {}; // issue.id -> issue
var _issuesByEntityID = {}; // entity.id -> set(issue.id)
var _validatedGraph = null;
var _deferred = new Set();
//
// initialize the validator rulesets
@@ -45,6 +45,11 @@ export function coreValidator(context) {
// clear caches, called whenever iD resets after a save
//
validator.reset = function() {
Array.from(_deferred).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred.delete(handle);
});
// clear caches
_ignoredIssueIDs = {};
_issuesByIssueID = {};
@@ -430,10 +435,11 @@ export function coreValidator(context) {
context.history()
.on('merge.validator', function(entities) {
if (!entities) return;
var ids = entities.map(function(entity) { return entity.id; });
utilCallWhenIdle(function() {
var handle = window.requestIdleCallback(function() {
var ids = entities.map(function(entity) { return entity.id; });
validateEntities(entityIDsToValidate(ids, context.graph()));
})();
});
_deferred.add(handle);
});
+11 -5
View File
@@ -2,12 +2,13 @@ import { dispatch as d3_dispatch } from 'd3-dispatch';
import { osmEntity } from '../osm';
import { utilRebind } from '../util/rebind';
import { utilArrayGroupBy, utilArrayUnion, utilCallWhenIdle, utilQsString, utilStringQs } from '../util';
import { utilArrayGroupBy, utilArrayUnion, utilQsString, utilStringQs } from '../util';
export function rendererFeatures(context) {
var dispatch = d3_dispatch('change', 'redraw');
var features = utilRebind({}, dispatch, 'on');
var _deferred = new Set();
var traffic_roads = {
'motorway': true,
@@ -333,6 +334,11 @@ export function rendererFeatures(context) {
features.reset = function() {
Array.from(_deferred).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred.delete(handle);
});
_cache = {};
};
@@ -541,9 +547,8 @@ export function rendererFeatures(context) {
// warm up the feature matching cache upon merging fetched data
context.history().on('merge.features', function(newEntities) {
utilCallWhenIdle(function() {
if (!newEntities) return;
if (!newEntities) return;
var handle = window.requestIdleCallback(function() {
var graph = context.graph();
var types = utilArrayGroupBy(newEntities, 'type');
// ensure that getMatches is called on relations before ways
@@ -552,7 +557,8 @@ export function rendererFeatures(context) {
var geometry = entities[i].geometry(graph);
features.getMatches(entities[i], graph, geometry);
}
})();
});
_deferred.add(handle);
});
+12 -11
View File
@@ -9,10 +9,7 @@ import rbush from 'rbush';
import { JXON } from '../util/jxon';
import { geoExtent, geoRawMercator, geoVecAdd, geoZoomToScale } from '../geo';
import { osmEntity, osmNode, osmNote, osmRelation, osmWay } from '../osm';
import {
utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilRebind,
utilCallWhenIdle, utilTiler, utilQsString
} from '../util';
import { utilArrayChunk, utilArrayGroupBy, utilArrayUniq, utilRebind, utilTiler, utilQsString } from '../util';
var tiler = utilTiler();
@@ -32,6 +29,7 @@ var _noteCache = { toLoad: {}, loaded: {}, inflight: {}, inflightPost: {}, note:
var _userCache = { toLoad: {}, user: {} };
var _changeset = {};
var _deferred = new Set();
var _connectionID = 1;
var _tileZoom = 16;
var _noteZoom = 12;
@@ -289,20 +287,18 @@ function parseXML(xml, callback, options) {
var root = xml.childNodes[0];
var children = root.childNodes;
utilCallWhenIdle(function() {
var handle = window.requestIdleCallback(function() {
var results = [];
var result;
for (var i = 0; i < children.length; i++) {
result = parseChild(children[i]);
if (result) results.push(result);
}
done(results);
})();
function done(results) {
callback(null, results);
}
});
_deferred.add(handle);
function parseChild(child) {
var parser = parsers[child.nodeName];
@@ -369,6 +365,11 @@ export default {
reset: function() {
Array.from(_deferred).forEach(function(handle) {
window.cancelIdleCallback(handle);
_deferred.delete(handle);
});
_connectionID++;
_userChangesets = undefined;
_userDetails = undefined;
+2 -6
View File
@@ -11,11 +11,7 @@ import {
import { osmEntity } from '../osm';
import { utilDetect } from '../util/detect';
import {
utilDisplayName, utilDisplayNameForPath,
utilEntitySelector, utilCallWhenIdle
} from '../util';
import { utilDisplayName, utilDisplayNameForPath, utilEntitySelector } from '../util';
@@ -763,7 +759,7 @@ export function svgLabels(projection, context) {
}
var throttleFilterLabels = _throttle(utilCallWhenIdle(filterLabels), 100);
var throttleFilterLabels = _throttle(filterLabels, 100);
drawLabels.observe = function(selection) {
+6 -12
View File
@@ -1,14 +1,7 @@
import _debounce from 'lodash-es/debounce';
import {
descending as d3_descending,
ascending as d3_ascending
} from 'd3-array';
import {
event as d3_event,
select as d3_select
} from 'd3-selection';
import { descending as d3_descending, ascending as d3_ascending } from 'd3-array';
import { event as d3_event, select as d3_select } from 'd3-selection';
import { t, textDirection } from '../util/locale';
import { svgIcon } from '../svg/icon';
@@ -19,7 +12,6 @@ import { uiDisclosure } from './disclosure';
import { uiMapInMap } from './map_in_map';
import { uiSettingsCustomBackground } from './settings/custom_background';
import { uiTooltipHtml } from './tooltipHtml';
import { utilCallWhenIdle } from '../util';
import { tooltip } from '../util/tooltip';
@@ -279,7 +271,6 @@ export function uiBackground(context) {
function update() {
if (!_pane.select('.disclosure-wrap-background_list').classed('hide')) {
updateBackgroundList();
}
@@ -388,7 +379,10 @@ export function uiBackground(context) {
// add listeners
context.map()
.on('move.background-update', _debounce(utilCallWhenIdle(update), 1000));
.on('move.background-update',
_debounce(function() { window.requestIdleCallback(update); }, 1000)
);
context.background()
.on('change.background-update', update);
+3 -3
View File
@@ -17,7 +17,7 @@ import { uiTagReference } from './tag_reference';
import { uiPresetEditor } from './preset_editor';
import { uiEntityIssues } from './entity_issues';
import { uiTooltipHtml } from './tooltipHtml';
import { utilCallWhenIdle, utilCleanTags, utilRebind } from '../util';
import { utilCleanTags, utilRebind } from '../util';
export function uiEntityEditor(context) {
@@ -330,13 +330,13 @@ export function uiEntityEditor(context) {
// reset the scroll to the top of the inspector (warning: triggers reflow)
if (_scrolled) {
utilCallWhenIdle(function() {
window.requestIdleCallback(function() {
var body = d3_selectAll('.entity-editor-pane .inspector-body');
if (!body.empty()) {
_scrolled = false;
body.node().scrollTop = 0;
}
})();
});
}
var presetMatch = context.presets().match(context.entity(_entityID), _base);
+7 -3
View File
@@ -10,7 +10,7 @@ import { geoSphericalDistance } from '../geo';
import { svgIcon } from '../svg/icon';
import { uiDisclosure } from './disclosure';
import { uiTooltipHtml } from './tooltipHtml';
import { utilCallWhenIdle, utilHighlightEntities } from '../util';
import { utilHighlightEntities } from '../util';
export function uiIssues(context) {
@@ -29,8 +29,12 @@ export function uiIssues(context) {
};
// listeners
context.validator().on('validated.uiIssues', utilCallWhenIdle(update));
context.map().on('move.uiIssues', _debounce(utilCallWhenIdle(update), 1000));
context.validator().on('validated.uiIssues',
function() { window.requestIdleCallback(update); }
);
context.map().on('move.uiIssues',
_debounce(function() { window.requestIdleCallback(update); }, 1000)
);
function addNotificationBadge(selection) {
-12
View File
@@ -1,12 +0,0 @@
// call a single function while idle.
// note the function should be of low priority
// and should not be returning a value.
export function utilCallWhenIdle(func, timeout) {
return function() {
var args = arguments;
var that = this;
window.requestIdleCallback(function() {
func.apply(that, args);
}, { timeout: timeout });
};
}
-1
View File
@@ -8,7 +8,6 @@ export { utilArrayUniq } from './array';
export { utilArrayUniqBy } from './array';
export { utilAsyncMap } from './util';
export { utilCallWhenIdle } from './idle';
export { utilCleanTags } from './clean_tags';
export { utilDetect } from './detect';
export { utilDisplayName } from './util';