So, here's my two cents.
Consolidation
Sheetworkers should, wherever possible, be consolidated. This is because both getAttrs and setAttrs are asynchronous events. This means that if you have two getAttrs that are fired from a single event, you can't control in what order they are fired. Additionally, each getAttrs call takes a noticeable amount of time to get the attribute values, and putting multiple getAttrs after each other will increase this time as each one can't fire till the call stack is empty. As an example to show how this affects performance at extreme levels. Lets say that you had an attribute change that affected 1000 other attributes. You could either A) do a getAttr for each attribute and then all the calculations you need for each one, or B) you could do a getAttrs of all 1000 at once and then do the calculations for each one. The getAttrs function takes very close to the same amount of time to get attribute values whether you're getting 1 attribute or 1000; let's say this is 50ms for the sake of this comparison. (EDIT: See addendum at bottom)
A)
Each getAttrs call has to be resolved independently and won't fire until the call stack is clear, so resolving all the getAttrs calls will take 50000 ms (or 50 seconds) + the time required for any calculations/logic you're doing with those values. So for all the effects of the attribute change to occur will take almost a minute
B)
Here, we do a single getAttrs (50ms) and a bunch of logic (which maybe takes 10's of ms). So for all the effects of the attribute change to be completed takes about 60ms (or about 0.06 seconds).
This correlation also means that figuring out everything that might be affected by an attribute change and grabbing every attribute value you might need to respond to an attribute change is exponentially quicker than doing getAttrs in response to the first attribute change and then having other events respond to those changes that will do other getAttrs and potentially trigger other events. Additionally, because the asynchronous events do not fire in a defined order and doing multiple of them at once can take so long, you can run into an issue where all the changes from a given attribute change haven't occurred yet, but the user has already started making other manual changes which now get added to the list of changes and might fire before the remaining effects of the first attribute change.
Here's some pseudo code examples of each of these:
Multiple getAttrs from a single event (Poor Performance)
on('change:attribute_name',(event)=>{
getAttrs(['control1'],(attr)=>{
setAttrs({change1:'yadda'});
});
getAttrs(['control2'],(attr)=>{
setAttrs({change2:'yadda'});
});
});
Cascading getAttrs (Worst Performance)
on('change:attribute_name',(event)=>{
getAttrs(['control1'],(attr)=>{
setAttrs({change1:'yadda'});
});
});
on('change:change1',(event)=>{
getAttrs(['control2'],(attr)=>{
setAttrs({change2:'yadda'});
});
});
Get everything all at once (Best performance)
on('change:attribute_name',(event)=>{
getAttrs(['control1','control2'],(attr)=>{
setAttrs({
change1:'yadda',
change2:'yadda'
});
});
});
Sheetworkers triggering API
A sheet that is being designed to be used by the community at large should NEVER be designed to require an API script; the ones that are currently in the repo have been grandfathered in. Requiring an API script makes your sheet unusable by non-pro users.
Additionally, the sheetworkers cannot trigger an API script in the way you're suggesting. Sheetworkers can't send any messages to chat, although they can trigger API scripts by causing changes to attributes; however this should not be relied upon if you are designing your sheet to require an API because the API won't be able to respond to these changes if the original event that caused the change was issued by the API itself. Essentially, you can do either of:
- User caused change -> API response
- User caused change -> Sheetworker response and change -> API response
But you can't do either of:
- API change -> API response
- API change -> Sheetworker Response -> API Response
I hope that helps,
Scott
ADDENDUM:
The 50 ms I used in the example is much longer than the getAttrs actually takes. A getAttrs takes just a couple milliseconds. This means that doing multiple concurrent getAttrs from a single event is actually not horribly inefficient, although is still less efficient than combining all of them. However, the setAttrs function takes ~100ms per run, so doing the cascading getAttrs method is actually much worse than any other method.