Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Script dependencies

I am having trouble building API scripts that depend on each other. I am extracting some common functionality (parsing certain types of API messages, for instance) into utility functions that I am trying to load before other scripts. However, Roll20 is not allowing me to control the order in which my scripts load. I have tried deleting the scripts and re-adding them in the order I want, but that doesn't seem to do anything. What I'd like is to be able to add all the scripts I want to use, then have some sort of drag-and-drop list where I can sort them in the proper loading order. Any suggestions how to get this working?
1438167325
The Aaron
Pro
API Scripter
The API works by concatenating all scripts together. The order of definition doesn't have to be before use. That said, there can definitely be problems if you are executing uninitialized code. The pattern I use (defined here by Brian:&nbsp; <a href="https://wiki.roll20.net/API:Cookbook#Revealing_Mod" rel="nofollow">https://wiki.roll20.net/API:Cookbook#Revealing_Mod</a>... ) allows a separation between initialization and execution.&nbsp; What errors are you getting?
I am also using the revealing module pattern for my scripts, but I am working on separate modules that depend on another common one. So I have API scripts like this: script1.js var MyUtilityModule = MyUtilityModule || (function() { &nbsp; ... }()); script2.js var MyModule = MyModule || (function(Util) { &nbsp; ... }(MyUtilityModule)); The issue I am getting is that the utility module is not defined unless the first script is loaded before the second. I have been able to reproduce this consistently. The problem is that, for whatever reason, Roll20 is not loading the scripts in any kind of deterministic manner that I can figure out. New scripts are not necessarily loaded last, so even though I deleted my scripts and added the utility before adding any others, it still is undefined when they try to execute.
1438191518
The Aaron
Pro
API Scripter
Right. Execution order is not guaranteed.&nbsp; Instead of passing in the dependency, you can just reference it using the global name. Not as elegant, certainly, but very functional.&nbsp; A step better is to reference a variable in the local module and provide a way of setting the object for that variable, then call it in an on('ready',...) handler to set the dependency. You can make use of the Null Object Pattern in your initialization to have a script that always functions.&nbsp; I'll go grab my laptop and get you a better example. Typing code on a phone sucks. :)
1438192887
The Aaron
Pro
API Scripter
So, this will work, regardless of order, provided you aren't executing code that depends on MyUtilityModule until it can be defined (such as after on('ready',...) or in response to some other event): var MyUtilityModule = MyUtilityModule || (function() { "use strict"; var someFunc = function() { }; /* ... */ return { someFunc: someFunc }; }()); var MyModule = MyModule || (function(Util) { "use strict"; var myFunc = function() { MyUtilityModule.someFunc(); }; /* ... */ }()); A more robust method is passing in the dependency during on('ready',...). &nbsp;This allows you to start up with a default implementation ( does nothing in this case, Null Object Pattern), as well as validate whatever is passed into be set: var MyModule = MyModule || (function(Util) { "use strict"; var utilityHandler = { someFunc: _.noop }, myFunc = function() { utilityHandler.someFunc(); }, SetUtilityHandler = function(uth) { if( _.isObject(uth) && _.has(uth,'someFunc') && _.isFunction(uth.someFunc)) { utilityHandler = uth; } }, /* ... */ return { SetUtilityHandler: SetUtilityHandler }; }()); on('ready',function(){ MyModule.SetUtilityHandler(MyUtilityModule); }); MyUtilityModule doesn't need to change in this case. Hope that helps!
That works like a charm. I'm going with the on ready approach so I can keep my modules more discrete. One thought I just had is whether we can broadcast and subscribe to custom events. I may give it a try and see what happens.
I just saw&nbsp; this topic , which seems to say that there isn't a solution in place right now.
1438199251
The Aaron
Pro
API Scripter
You can't use on(), but don't let that stop you! Check out the latest version of GroupInitiative and Bump. GroupInitiative provides notifications of when it changes the turn order, Bump subscribes to those notifications and adjusts the turn order in response. This is the Observer Design Pattern.&nbsp;
1438199392
The Aaron
Pro
API Scripter
Yep, exactly! &nbsp;:)