Currently, I’m trying lockservice in Google App Script to handle concurrency on my webapp. However, when I implement it, it did not work.
Whenever a user click on the button, it will get the website address value in the google sheet and open a new window to go to the website. Then, it will update the value in my google sheet with the value of a new website address.
on this webapp, it will cycle through 3 websites Google -> Youtube -> Facebook
The problem:
When I tried testing it for concurrency with clicking the button fast, it will return the same website. For example, if I clicked it twice, it will open 2 new window of Google, but the value in the google sheet will be updated to Facebook, which skip the Youtube.
I tried implement lockservice but it did not work, maybe I implement it wrongly.
this is my HTML code:
<html> <head> <base target="_top"> </head> <body> <div class="content"> <h1>Please Click Below</h1> <!-- <h2><?=web?>:</h2> --> <button class="button" id = "btn" type="submit" >Open Window</button> </div> <script> document.getElementById("btn").addEventListener("click", doStuff); var web = ""; function doStuff() { google.script.run.withSuccessHandler(openWebsite).getWebsite(); } function openWebsite(web) { if (web === "Google") { window.open("https://www.google.com/"); } else if (web === "Youtube") { window.open("https://www.youtube.com/"); } else { window.open("https://www.facebook.com/"); } google.script.run.setWebsite(); } </script> </body> </html>
My code.gs:
var url = "google sheet url"; var web = ""; function doGet(e) { let tmp = HtmlService.createTemplateFromFile("index"); let output = tmp.evaluate().addMetaTag('viewport', 'width=device-width, initial-scale=1'); return output; } function setWebsite () { var ss = SpreadsheetApp.openByUrl(url); var ws = ss.getSheetByName("website"); web = ws.getRange(1,1,1,1).getValue(); var lock = LockService.getScriptLock(); //del lock.tryLock(5000); //del if (lock.hasLock()) { //del if (web === "Google") { ws.getRange(1,1,1,1).setValue("Youtube"); } else if (web === "Youtube") { ws.getRange(1,1,1,1).setValue("Facebook"); } else { ws.getRange(1,1,1,1).setValue("Google"); } var xs = ss.getSheetByName("data"); xs.appendRow([new Date(), web]); lock.releaseLock(); //del } } //del function getWebsite() { var lock = LockService.getScriptLock(); lock.tryLock(5000); // wait 5 seconds try to get lock if (lock.hasLock()) { var ss = SpreadsheetApp.openByUrl(url); var ws = ss.getSheetByName("website"); var web = ws.getRange(1,1,1,1).getValue(); lock.releaseLock(); return web; } } // function getWebsite() { // var lock = LockService.getScriptLock(); // try { // lock.waitLock(5000); // wait 5 seconds try to get lock // } catch (e) { // Logger.log('Could not obtain lock after 5 seconds.'); // } // Utilities.sleep(1000); // var ss = SpreadsheetApp.openByUrl(url); // var ws = ss.getSheetByName("website"); // var web = ws.getRange(1,1,1,1).getValue(); // lock.releaseLock(); // return web; // //lock.releaseLock(); // }
ps. I tried two different ways (on the comment part in code.gs) that I can find on Stackoverflow and youtube but still no success.
Please help. Thank you.
Advertisement
Answer
I thought that in your script, when the button is clicked, google.script.run.withSuccessHandler(openWebsite).getWebsite()
is run and also google.script.run.setWebsite()
is run in the function openWebsite
. In this case, the LockService is used for each function of getWebsite()
and setWebsite()
. I thought that this might be the reason of your issue. So, in your script, how about the following modification? In this modification, one LockService is used for the functions of getWebsite()
and setWebsite()
.
HTML&Javascript side:
Please modify openWebsite(web)
in your Javascript side as follows.
From:
google.script.run.setWebsite();
To:
// google.script.run.setWebsite();
- In this modification,
google.script.run.setWebsite();
is removed.
Google Apps Script side:
Please modify getWebsite()
in your Google Apps Script side as follows.
From:
var web = ws.getRange(1,1,1,1).getValue(); lock.releaseLock();
To:
var web = ws.getRange(1, 1, 1, 1).getValue(); setWebsite(); // Added lock.releaseLock();
- In this modification,
google.script.run.setWebsite();
is removed.
Note:
- When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
- You can see the detail of this in the report of “Redeploying Web Apps without Changing URL of Web Apps for new IDE“.