Reputation: 33
I wrote a google apps script code, it will open a google spread sheet, and list the values by row, but there are 2 problems: 1. The output by random order. 2. The div text which id "loding" change to "Finished!" before list all of values. I thought the script will wait for server-side function return when I run it by "withSuccessHandler()", but it's not. How can I correct it?
index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function jsListValue() {
// Get count.
google.script.run.withSuccessHandler(function(count) {
// List all values.
for( count; count>0; count=count-1) {
// Get a value.
google.script.run.withSuccessHandler(function(content) {
// Shows in "output".
var new_div = document.createElement("div");
new_div.appendChild(document.createTextNode(content));
document.getElementById("output").appendChild(new_div);
}).gsGetValue(count);
}
// Change loding notice.
document.getElementById("loding").innerHTML = "Finished!";
}).gsGetCount();
}
</script>
</head>
<body onload="jsListValue()">
<div id="output"></div>
<div id="loding">Loding now...</div>
</body>
</html>
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function gsOpenSheet() {
// Return sheet of the note data.
return (SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getSheetByName("sheet1"));
}
function gsGetCount() {
// Return last row index in this sheet.
return (gsOpenSheet().getLastRow());
}
function gsGetValue(index) {
// Return value in the (index,1).
return (gsOpenSheet().getRange(index,1).getValue());
}
Upvotes: 3
Views: 3072
Reputation: 1
As hinted by @Iuri Pereira If you return a parameter from the google script code, and then use it in the page javascript, then the procedure runs synchronously.
HTML:
<button onclick="google.script.run.withSuccessHandler(js_function).gs_code();">action</button>
GS:
function gs_code() {
// do Something;
return true;
}
HTML javascript:
function js_function(gs_return_value) {
console.log(gs_return_value);
}
Upvotes: 0
Reputation: 16
google.script.run
is asynchronous, which means that is impossible to predict in what order gsGetValue(count)
will return. When you're using withSuccessHandler
you must perform the next action inside the callback function.
My suggestion is to get all the range you want and put it on an array. You can create a serverside function to do this. The code would look like this:
//Serverside function
function getDataForSearch() {
const ws = SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx").getSheetByName("sheet1");
return ws.getRange(1,1,ws.getLastRow(),1).getValues();
}
getValues()
will return an array of arrays that should contain all values from the range specified. More information about here
On your client-side, the script should be like this:
//array to get the data from getRange()
var data;
function jsListValue() {
google.script.run.withSuccessHandler(function(dataReturned){
data = dataReturned;
var new_div;
data.forEach(function(r){
new_div = document.createElement("div");
new_div.appendChild(document.createTextNode(r[0));
document.getElementById("output").appendChild(new_div);
});
document.getElementById("loding").innerHTML = "Finished!";
}).getDataForSearch();
}
Upvotes: 0
Reputation: 1780
You want to use withSuccessHandler
Docs
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function onSuccess(numUnread) {
var div = document.getElementById('output');
div.innerHTML = 'You have ' + numUnread
+ ' unread messages in your Gmail inbox.';
}
google.script.run.withSuccessHandler(onSuccess)
.getUnreadEmails();
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
Upvotes: 2
Reputation: 2196
GAS is very similar to Javascript, and all calls to Google's server side functions are asynchronous. You cannot change this (at least I haven't seen any doc reg. that).
What you can do, is, use a callback function on the client side which polls the server for a "success" return value. It'll keep polling it say for 1 minute, or else exit. Let it set a client flag to "true" if the success value is returned by the server. Nothing should proceed on the client side, unless the flag is true. In this way, you can control what happens on the client side.
Upvotes: 4