Skip to content

How to make the client-side code wait for the full execution of google.script.run?

I’ve got a Google Apps Script WebApp that relies on an array of objects that are generated from a Google Spreadsheet. The app uses jquery and miniSearch to provide user functionality.

Currently, I run the server-side function with a success handler at the beginning of the HTML tag and update a “global” variable with the array of objects declared before it.

Index.html:

<script>
let data
google.scripts.run
.withSuccessHandler(payload=>{
data = payload}).getLinks() //[{link:body}, {link1:body1}]
setTimeout(()=>{
const documents = data
miniSearch = new miniSearch(...)
miniSearch.addAll(documents)}, 2500)
...
</script>

Code.gs

function getLinks(){
        .
        .
        .
        let values = sheet.getRange(1, 1, lastRow, lastCol)
        for (let row = 0; row < lastRow; row++) {
            let entry = new Data(row + 1, values[row][0], values[row][1], values[row][2], values[row][3], values[row][4], values[row][5], values[row][6])
            allTitles.push(entry)
    }
return allTitles
}

I simulate waiting for the google.scripts.run to finish by setting a setTimeout of 2500ms on the miniSearch indexing execution (which relies on the aforementioned array) and most of the time it works.

The problem is, that before the app is ran for the first time in a given period, the contents are not cached and the execution takes longer than the setTimeout, thus, as expected, the searching function bugs out since it’s got no data to run on.

My question is: How to make the code wait and confirm that google.scripts.run has returned the needed data?

I have tried doing it with regular promises or async await functions, but to my understanding, google runs its server functions asynchronously and there’s no way to tell (in code, that is) if it’s finished, I’ve tried running it as $(function(){google.script.run..}) as to try to load the contents as soon as the DOM is loaded, but to no avail..

Answer

The only way to make sure it finishes is to do this. If its unresponsive then the problem lies in getLinks, Data, or whatever miniSearch is.

<script>
  const documents = null;
  google.scripts.run.withSuccessHandler( function(payload) {
    documents = payload;
    miniSearch = new miniSearch(...);
    miniSearch.addAll(documents);
  }.getLinks(); //[{link:body}, {link1:body1}]
...
</script>