-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support setup to return Promise #294
base: master
Are you sure you want to change the base?
Conversation
@@ -686,43 +686,93 @@ function prepPluginsToLoad() { | |||
// executes setup function of plugin | |||
// and collects info for About IITC | |||
function safeSetup (setup) { | |||
if (!setup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- You should avoid mixing main changes with whitespace changes
- https://github.com/IITC-CE/ingress-intel-total-conversion/wiki/Code-Style
Have I understood correctly that the only reason of proposed changes is performance gain from parallel plugins' setup execution? |
No Plugins that use Promises are currently executed and some undetermined time after the setup call. This can have unwanted side effects. One example if you add a BaseLayer, that was previously selected IITC, will not select the Layer again since it isn't available when the selection runs because the call hasn't finished yet so you have to run the selection code again in the setup. With this change the execution order of things is mainated also for plugins that want to use Promises |
You mean that some plugins use promises internally for own purposes.
We had 2 similar plugins: Bing and Yandex. So 2 questions:
|
Every Plugin that want to use Promises (currently they can't) and relies on any of the lines after the loadPlugin(); call in bootjs to actually run after the setup This gets worse if you have a "boot" plugin because their is just more stuff to run later. |
'Any' is good. And I support your idea. And I'd prefer not be too quick on implementation, as we used to have differing plans for values returned from setup. |
i created a quick plugin that makes the issue visible. it is a copy of the openstreetmap plugin but with an added delay till the layers are available to simulate more work beeing done (otherwise the setup might be to fast to recognize)) |
A plugin that requires a delay in boot time is a bad plugin. So this behaviour is just fine. Promises are for event handling not for multithreading. |
I am not so categorical as @McBen, but still I am not convinced enough that we absolutely need some special support for promises.
Look our current Google, Bing and Yandex - all of them have deferred initialization. P.S. |
The actual execution time of the real script is really fast the only Problem is that it expect things like the iitcLoaded hook or the basemap layer selection to be run when the loading of everything is done and not before. And the Problem is that i have to load data async before the setup is finished. (indexedDB) The Problem with wrong loading occures with the real plugin arround 50% of the time. The Problem is that you basically loose all ability to guaranteed run before setup is finished when you do anything that is async like load from indexdb/AJAX requests etc etc. The long delay in the demo plugin is only to showcase the problem and guarantee it will happen every time. |
Are you sure that you have to do it before setup returned? |
real example MapLayer that requires an APIKey that is stored in the indexdb. |
Good example.
|
Some general thoughts:
But it is ridiculous to stick to ancient ES in 2019, so... |
I see here wrong usage of !window.iitcLoaded && addHook('iitcLoaded', hookFunc); || hookFunc(); But I agree that here promise will be much more appropriate that hook (we are considering this too, e.g. see #76 (comment)). As for your gist sample, alternatively it could be fixed like this: setup : function(){
let iitcLoaded = new Promise(resolve => {
addHook("iitcLoaded", resolve);
});
let myrequest = new Promise(//......
Promise.all([iitcLoaded, myrequest]).then(() => {
window.plugin.mapTileOpenStreetMap.addLayer();
});
} ( |
And finally (honestly, it's rather offtopic here, but anyway), speaking about reasonable api of your sample plugin: there is no need to expose any of internal functions in plugin's namespace, as (in your sample) no one will be able to gain from it. So I would propose slightly different structure for it: // use own namespace for plugin
let mapTileOpenStreetMap= {};
window.plugin.mapTileOpenStreetMap = mapTileOpenStreetMap;
mapTileOpenStreetMap.layers = { // public, possible to override
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png': 'OpenStreetMap',
'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png': 'Humanitarian',
};
function addLayer() { // private
function setup() { // private |
a34b800
to
7b9edd5
Compare
This Pull request is related to #76
Currently a setup function that returns a promise will be executed "sometimes" after the loadPlugins() call but the load plugins call doens't wait till the promise is resolved.
This change allows a setup function to return a Promise and have the setup function be executed at the same time as other setup functions that have the same priority.
It also maintains the execution order of the other parts so for example layer selection code doens't run before the map layers are added by the plugin.
This change is also compatible with normal setup functions so plugins do not need to change to promises but can use whatever style they like.
Possible Improvements:
load plugins in parallel currently all normal setup functions run sequenqually in a single wrapper Promise. We could change this by wrapping each plugin in his own wrapper
evaluate the results of Promise.allSettled() currently it we do not react at all to a plugin failing to load.