Locking the Properties until the page is fully loaded in HtmlService

72 views
Skip to first unread message

Martin Mullan

unread,
Jan 6, 2020, 5:19:09 PM1/6/20
to Google Apps Script Community
Hello community,
I have written a web app that takes my students email address from the url; it stores the email address in the scriptproperties and then uses this in code.gs as the google.script.run functions are run in window.onload of the jscript file. The pages load fine as long as I don't open another student's page in quick succession after another; the properties gets overwritten and I end up with a mixture of student data depending on when the second page was opened.

I have tried using a scriptlock and userlock but it is the evaluation of the template that is taking the time and the lock gets released far too early.

doGet(e) {
var lock = LockService.getScriptLock();    
lock.waitLock(15000);
     if (lock.hasLock()) {
        var userFilter = e.parameter.Email; 
        PropertiesService.getScriptProperties().setProperty('userEmail', userFilter);
        var template = HtmlService.createTemplateFromFile('Index');   
        var page = template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);       
        lock.releaseLock();    
        return page
     }
}

How can I get the lock to release after the page has fully loaded so that the properties value doesn't get overwritten?

Thanks for your time.
Mart.

Alan Wells

unread,
Jan 6, 2020, 7:49:21 PM1/6/20
to Google Apps Script Community
Pass the students email to your index page into a hidden <div> element, and it will be available to the browser as soon as the page loads.
You can use a printing scriptlet to put the students email into the html into a hidden html element.
The students email will be available at any time to the browser.

You are already using templated html.  As soon as the template is evaluated, the students email will be put into the <div>
At that point there is no need to have it in script properties anymore because it's available to the browser.

If the students email needs to be passed back to the server, you can get it out of the hidden div at any time.

If there is a lag in Properties service being able to immediatly retrieve a value just saved, then you'd need to implement something like an exponential back off in the scriptlet, to make sure it got retrieved.

I'm not sure if you could put the email into a global instead of properties service.  If you did put it into a global, you wouldn't need to worry about any lag in Properties Service between saving and getting the property.  But if another user loads the Web App, I'm not sure if the global gets immediately wiped out, or if each user is running a different instance of the code.

<div style="display:none" id="idThisStudentsEmail"><?!= PropertiesService.getScriptProperties().getProperty('userEmail') ?></div>

<script>
  window
.onload = function() {
   
var theStudentsEmail;
   
    theStudentsEmail
= document.getElementById('idThisStudentsEmail').textContent;//Get the students email out of the div element
 
    console
.log('theStudentsEmail: ' + theStudentsEmail)
 
}

</script>

Martin Mullan

unread,
Jan 6, 2020, 7:59:04 PM1/6/20
to google-apps-sc...@googlegroups.com
Thanks Alan,
That makes sense. I do pass the email address to the server in order to get the student's data via google.script.run.
Would be able to give me an example of how I can access the hidden div in order to make those calls work?
Cheers, Mart.



--
You received this message because you are subscribed to a topic in the Google Groups "Google Apps Script Community" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-apps-script-community/Y1ILdHujPu0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/0e285c42-bf51-43b5-97e0-93b8bc28abb8%40googlegroups.com.

Important Information

______________________

This correspondence, and any files transmitted with it, are for the named person(s) use only. They may contain confidential or legally privileged information or both. No confidentiality or privilege is waived or lost by any mis-transmission. If you receive this correspondence in error, please immediately delete it from your system and notify the sender. You must not disclose, copy or relay on any part of this correspondence if you are not the intended recipient.

Any opinions expressed in this message are those of the individual sender, except where the sender expressly, and with authority, states them to be the opinions of The Kuala Lumpur Alice Smith School ("KLASS"), a school wholly-owned by The Alice Smith Schools Association ("ASSA").

Neither the sender nor KLASS warrants that any communication via the internet is free of errors, viruses, interception or  interference.

______________________

Alan Wells

unread,
Jan 6, 2020, 8:06:01 PM1/6/20
to Google Apps Script Community
 You can use:

var email = document.getElementById('idThisStudentsEmail').textContent;

To get the email out of the <div> element at any time.
The:
document.getElementById()

method is part of the DOM (Document Object Model) of HTML.
People often think that "document.getElementById()" is JavaScript but it's not.

Martin Mullan

unread,
Jan 7, 2020, 4:44:29 PM1/7/20
to Google Apps Script Community
Thanks Alan, that has worked a treat 😎

If you are up for another challenge...
My original code plots an Apexchart that requires the script to called after the div has been defined:

<div id="chartTerm2"></div>
<script>google.script.run.withSuccessHandler(drawNEWDonutChart2_1).getCommendationsByTerm();</script>

For the updated hidden div version I altered the google.script.run to google.script.run.withSuccessHandler(drawNEWDonutChart2_1).getCommendationsByTerm(email); like all the others but I got a reference error email not defined.
I tried rewriting the code.gs to avoid using the jscript. 
I tried building a function into the <script> tag, which stopped the error but still doesn't populate the chart...and console.log doesn't want to work so I don't know what is going wrong.
Any ideas on how to make it work?

Thanks again :)

Alan Wells

unread,
Jan 7, 2020, 8:58:32 PM1/7/20
to Google Apps Script Community
console.log() should work no matter what, unless you have an uncaught error, and all your HTML and JavaScript is not loading when the Web App is loaded.  Do you have an error in the browser developer tools stating that it can't find a function, or there was an uncaught error?
Reply all
Reply to author
Forward
0 new messages