-1

Could someone please help in controlling the flow of the google script code. Simply, I need to

  1. extract data from google sheet.
  2. then & only then represent it in the UI.

The google.script document says that:

google.script.run is an asynchronous client-side JavaScript API available in HTML-service pages that can call server-side Apps Script functions.

However, In my case I need to wait until server function return its value.

Note No Promise() in google script .

Note I have tried many mixtures of callback but without luck.

The following code is simulated from my native script & produce the same error. I expect to have the following log :

line NUM:1 start

line NUM:2 , registerdProducts length = 1004

lineNUM: 3 Data has been retrieved

line NUM:4 Build UI

But I have undesirable flow of the code, with unexpected log

line NUM:1 start

lineNUM: 3 Data has been retrieved

line NUM:4 Build UI

line NUM:2, registerdProducts length = 1004

the most important impact that: the createRows is called before preperation of its data & the UI will show nothing.

This is the Javascript.html code:

<script>
var sheetId            = "MyID";
var productsRange      = "Variables!I2:I"
var registeredProducts =[];

function onSuccessDo(products){
 /// assign the product list to the registeredProduct (global variable) .
 registeredProducts=products;
 console.log("line NUM:2, registerdProducts length = " , registeredProducts.length )
 };


function createRows(){
/// This function will add the prodducts to the UI
console.log("line NUM:4, Build UI" )
for (var x in registeredProducts , x < registeredProducts.length , x++){
    ///Adding the product in rows. 
    }
 }

function getProducts(){
/// This function will retrive the products from ths sheet & assign them to the global variable registeredProducts
console.log("line NUM:1, start")
var products = google.script.run.withSuccessHandler(onSuccessDo)
                                  .getDataFromSheet( sheetId, productsRange);
console.log("line NUM: 3, Data has been retrieved")
};

document.addEventListener('DOMContentLoaded', function() {
getProducts();
createRows();
/// use registeredProducts in other functions
/// here
       });

& This the getDataFromSheet function in Code.js:

function getDataFromSheet(ID , range){
  var sheet = SpreadsheetApp.openById(ID)  
  data = sheet.getRange(range).getValues();
  for (x in data ){
      if (data[x] == "" ){
          delete data[x]
          }}

 return   data;    
 }
Community
  • 1
  • 1
tabebqena
  • 1,204
  • 1
  • 13
  • 23

1 Answers1

1

You have two ways:

  1. You can load data on the server-side and push it to the client-side as a variable.
  2. Your case (loading from client)

1) Server.gs:

template = HtmlService.createTemplateFromFile('client.html');
template[some key] = 'some val';

2)

Javascript.html

<script>
var sheetId            = "MyID",
    productsRange      = "Variables!I2:I",
    registeredProducts = [];

function onSuccessDo(products)
{
    registeredProducts = products;
    console.log("line NUM:2, registerdProducts length = ", registeredProducts.length );
    console.log("line NUM:3, Data has been retrieved");
    createRows();
};


function createRows()
{
    console.log("line NUM:4, Build UI");
    for(var x in registeredProducts , x < registeredProducts.length , x++)
    {
        // code...
    }
}

function getProducts()
{
    console.log("line NUM:1, start")
    google.script.run
                    .withSuccessHandler(onSuccessDo)
                    .getDataFromSheet(sheetId, productsRange);
};

document.addEventListener('DOMContentLoaded', function(){
    getProducts();
});
</script>
FLighter
  • 389
  • 1
  • 4
  • 17
  • Thanks for reply, The first choice is static way to load data only one time at the start of the execution. – tabebqena Feb 06 '18 at 10:20
  • Thanks for reply. I need to call the "createRows" funcion after the "DOMConentLoaded", not after getting data from the server side. because First: before that event we got error from createRows (undefined objects) &second we call 'getProducts' then 'getPrices' etc & finally 'createRows' – tabebqena Feb 06 '18 at 10:27
  • 2
    @tabebqena, in this case, you will have to make a chain of calls and in each onSuccess function add the next function call. – FLighter Feb 06 '18 at 10:33
  • Is there is a better way – tabebqena Feb 06 '18 at 10:35
  • @tabebqena, unfortunately, I didn't find – FLighter Feb 06 '18 at 10:38