0
          • March 14 addition

Why would data returned by a function not be seen by its successHandler function?

Here is a smaller example:

<!DOCTYPE html>
<html>
  <head>
    <!--  tinyTestHtml.html -->
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Choose a class</title>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('cssStyle').getContent(); ?>
  </head>
  <body>
    This is the body


    <script>
      window.onload = function() {
        console.log('hah! it ran. ');
        google.script.run
          .withSuccessHandler(afterServerRepl)
          .listCourses();
       };

       window.afterServerRepl = function(e) {
         console.log('Server reply was successful!');
         console.log(JSON.stringify(e) );
       };
    </script>
  </body>
</html>

The console logs in listCourses show data found and returned but the successHandler JSON.stringify prints null. This code is from Run a Google apps script automatically upon loading a Google Site? I do not know how to write functions in that format but it was from Alan Wells and was the accepted answer. posted new question GAS Data from server side function not seen in successHandler function in HTML

            • end March 14 addition

I found the picker very difficult especially when creating code to share. I have had the Tanaike https://gist.github.com/tanaikech/96166a32e7781fee22da9e498b2289d0 working as written and have used it for only folders or only spreadsheets. I have tried to create a more generalized version and now even though getFiles logs show files found the importData function sees null. There is no code between these two as importData is called from the successHandler.

          • March 13
  1. this code is pretty much as Tanaike wrote it other than I am passing a mime type. It works when I select folders but fails when I select spreadsheets.

    $(function() { console.log('1 unnamed function' ); const rootfolderId = "root"; console.log('2 before call getFiles w 2 rootfolderId: ' + rootfolderId ); console.log(' mimeType: ' + mimeType ); google.script.run .withSuccessHandler(importData) .getFiles(rootfolderId, rootfolderId, mimeType ); console.log('3 after successHandler(importData) .getFiles(rootfolderId' );

The console logging is below

in initialize
1 unnamed function
2 before call getFiles w 2 rootfolderId: root
    mimeType: application/vnd.google-apps.spreadsheet
3 after successHandler(importData)  .getFiles(
0 in importData e:  null
userCodeAppPanel:136 Uncaught TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at importData (userCodeAppPanel:136)
    at ef (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:74)
    at VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:15
    at kg.P (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:102)
    at Kd (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:50)
    at a (VM9 47138931-mae_html_user_bin_i18n_mae_html_user.js:48)

The logging from the call to getFiles shows lots of data but the successHandler(importData) sees NULL! Where did the data disappear to?

  1. Problem: the console log message "3 after successHandler(importData) .getFiles(" is written out before the message that importData failed. I guess this is just a timing issue.
          • end March 13 update

The html

<!DOCTYPE html>
<html>

<head>
    <!-- tanaikeFileListHtml.html -->
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>tanaikeFileListHtml</title>
    <base target="_top">
    <!-- Tanaike's code  -->
    <!-- https://gist.github.com/tanaikech/96166a32e7781fee22da9e498b2289d0 -->


    <style>
       ... left out for brevity
    </style>
</head>

<body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.js"></script>
    <div id="parent">
        <div id="child">
            <!--https://stackoverflow.com/questions/30033459/how-to-pass-a-parameter-to-html   -->
            <!-- <h2 id="myTitle"></h2>   -->
            <!-- <h2 id="myTitle" class='notVisible'></h2>   -->
            <h2 class='centeredBold'>Be patient!</h2>
            <p class='centeredBold'>
                <br />When you select a file or folder the window will close.
            To backup select './' at the top of the list.
    </p>
                <select id="select_file"></select>
                <p id="id"></p>
                <span class='buttons'>
    <button type='button' onclick='buttonClicked()'>Select</button>
    <button type='button' onclick='google.script.host.close()'>Close</button>
    </span>
                <p id='data_in' class='notVisible'>
                    <?= passType ?>
                </p>
        </div>
    </div>
    <script>
        var alldata = {};
var mimeType;
var passType;

function initialize() {
  console.log('in initialize');

  // get input type from the HTML
  passType = document.getElementById("data_in").textContent;
  passType = passType.replace(/\s/g, '');  // remove spaces
  switch ( passType ) {
  case 'folder' : 
    mimeType = 'application/vnd.google-apps.folder';
    break;
  case 'spreadsheet' :
    mimeType = 'application/vnd.google-apps.spreadsheet';
    break;
  case 'slide' :
    mimeType = 'application/vnd.google-apps.presentation';
    break;
  case 'document' :
    mimeType = 'application/vnd.google-apps.document';
    break;
  case 'form' :
    mimeType = 'application/vnd.google-apps.form';
    break;
  case 'EVERYTHING' :
    console.log('passType EVERYTHING, setting mimeType to null');
    mimeType = null;
    break;
  default :
    console.log('input inType: ' + passType + ' setting mimeType to null');
    mimeType = null;
  }
}
// use onload or use jquery to call your initialization after the document loads
window.onload = initialize();

function buttonClicked()  {
  console.log('In buttonClicked');

  var keys = Object.keys(alldata);
  console.log('keys: ' + keys);
  var selectedId = keys[keys.length-1]
  console.log(' going to run returnSelId selectedId: ' + selectedId );
  google.script.run
               .withSuccessHandler(output)
               .returnSelId( selectedId, passType );
  console.log('after successHandler(output)  .returnSelId(selectedId, inType)' );       
  google.script.host.close();
}

$(function()    {
  console.log('1 unnamed function' );
  const rootfolderId = "root";
  console.log('2 before call getFiles w 2 rootfolderId: ' + rootfolderId );
  console.log('                               mimeType: ' + mimeType );
  google.script.run
        .withSuccessHandler(importData)
        .getFiles(rootfolderId, rootfolderId, mimeType );
  console.log('3 after successHandler(importData)  .getFiles(rootfolderId' ); 

  // triggered by change in html select element with id='select_file'
  $("#select_file").change(function() {
    console.log('4 in $(\'#select_file\').change function' );
    var id = $( '#select_file').val();
    console.log('   id: ' + id );
    var disp = $('#select_file option:selected').text();
    if (~disp.indexOf("folder") || ~disp.indexOf("../")) {
      $('#select_file > option').remove();
      if (alldata[id]) {
        var dat = {};
        dat[id] = alldata[id];
        console.log('5 before importData - dat: ' + dat );
        importData(dat);
        return;
      } else {
        console.log('6   after else - id: ' + id );
        google.script.run
              .withSuccessHandler(importData)
              .getFiles(id, rootfolderId, mimeType );
        console.log('7 after successHandler(importData) .getFiles(id ' );  
        return;
      }
      console.log('8 after ~disp.indexOf("folder") || ~disp.indexOf("../") ' );  
      return;
   }    else    {
      console.log('9 else - files not folders' );
      $('#select_file > option').remove();
      if (alldata[id]) {
        var dat = {};
        dat[id] = alldata[id];
        console.log('10 before importData' );
        console.log('               dat: ' + dat );
        importData(dat);
        return;
      } else {
        console.log('11               after else - id: ' + id );
        google.script.run
              .withSuccessHandler(importData)
              .getFiles(id, rootfolderId, mimeType );
              
        console.log('12 after call getFiles' );
        return;
      }
      console.log('13 end  else - files not folders' );
      return;
   }

//  Replaced this with buttonClicked() 
//    google.script.run
//          .withSuccessHandler(output)
//          .returnSelId(selectedId, mimeType);  ??
//          .returnSelId(selectedId, inType);  ??
  });
});

/**
 * gets data returned from successful call to getFiles
 */
function importData(e) {
console.log('0 in importData e: ', JSON.stringify(e) );
  var key = Object.keys(e)[0];
console.log('1 key: ', key );
console.log('2 alldata[key]: ', alldata[key] );
  if (!alldata[key]) alldata[key] = e[key];
console.log('3 alldata[key] set to e[key]' );
  if (e[key]["keyparent"]) {
console.log('4 e[key]["keyparent"] exists' );
    $('#select_file').append($('<option>')
                     .html("./" + e[key]["keyname"])
                     .val(key));
    $('#select_file').append($('<option>')
                     .html("../")
                     .val(e[key]["keyparent"]));
  } else {
console.log('5 e[key]["keyparent"] does not exist' );
    $('#select_file').append($('<option>')
                     .html("./" + e[key]["keyname"])
                     .val(key));
  }
  for (var i=0; i < e[key]["files"].length; i++) {
    $('#select_file').append($('<option>')
      .html(e[key]["files"][i].mimeType == "folder" ? "[Folder]" + e[key]["files"][i].name : e[key]["files"][i].name)
      .val(e[key]["files"][i].id)
    );
  }
}

function output(res)  {
  console.log('in output w res: ' + res);
  $('#id').text(res);
}
    </script>
</body>

</html>

The getFiles logging

Mar 9, 2021, 11:19:24 AM    Debug   - - - - - - - - - Begin getFiles inMimeType:  application/vnd.google-apps.spreadsheet
Mar 9, 2021, 11:19:24 AM    Debug    da:  {}
Mar 9, 2021, 11:19:25 AM    Debug        # files after folders.hasNext:  6
Mar 9, 2021, 11:19:25 AM    Debug        # files after files.hasNext:  6
Mar 9, 2021, 11:19:25 AM    Debug   # after sort: ; 5
Mar 9, 2021, 11:19:25 AM    Debug        # files after both while loops:  11
Mar 9, 2021, 11:19:25 AM    Debug        # files after both while loops JSON.stringify(data): 
Mar 9, 2021, 11:19:25 AM    Debug         {"0AO8tjYr48IZIUk9PVA":{"keyname":"My Drive","keyparent":null,"files":[{"name":"FluencyTutor","id":"1_1SfrnyRdauXapevULnJ3ijZ-76Ewxnu","mimeType":"folder"},{"name":"Rosters","id":"1VLFlSzSn49TcNkNBjkEMavbxhZ8DEZ1n","mimeType":"folder"},{"name":"Meet Recordings","id":"1V2oiVRCQagj_BlERFuyExNCP-SQ92npA","mimeType":"folder"},{"name":"My book - I want to read better","id":"1_Y7yfTroZWfh_3dQRL_AUtgJ8Ot1vXRf","mimeType":"folder"},{"name":"Google App Scripts","id":"1LSX43dtlbZBeh2B9IOMyRZ8nL4pVNdq8","mimeType":"folder"},{"name":"Classroom","id":"0B-8tjYr48IZIflBPT2IxazdEc0lLZk8wcWxZQUZjbVNST3IyeVVFdTdKRGF6TVNWXzhrVHc","mimeType":"folder"},{"name":"Copy of Explore example","id":"153Osux5K0SYN2DrQ7WTspBFnfKrEl3L1eT8WF5Id2H0","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2001-01-01T06:00:00.000Z","id":"1bB4yCQCRxyYpOsx3tzQIktKhiOAhlXAH6oU5gaviQX0","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2019-20 ELL contact list","id":"1nzjE4IiCbnYH855pzTJN6TRs91hZVBUq3lioi_i6ZjU","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2020-2021 AEL Teacher Rosters","id":"1tS0-s9pY7iVMcvqjpqGykYjs0bJM9VC6Uz3Ggg1QE1I","mimeType":"application/vnd.google-apps.spreadsheet"},{"name":"2020-2021 ESL Teacher Rosters","id":"1Ktuh7oDunCxKQo5Q2-1OY10Zsdc9ILEqPdg62Y4_THg","mimeType":"application/vnd.google-apps.spreadsheet"}]}}
Mar 9, 2021, 11:19:25 AM    Debug   End getFiles

The getFile code

function getFiles(e, rootFolderId, inMimeType) {
  console.log('- - - - - - - - - Begin getFiles inMimeType: ', inMimeType );
  
  var data = {};
  var fileArr = [];
  var idn = e;
  e = e == "root" ? DriveApp.getRootFolder().getId() : e;
  data[e] = {};
  data[e].keyname = DriveApp.getFolderById(e).getName();
  data[e].keyparent = idn == rootFolderId
    ? null : DriveApp.getFolderById(e).getParents().hasNext()
    ? DriveApp.getFolderById(e).getParents().next().getId() : null;
  data[e].files = [];
  var da = idn == "root" ? DriveApp.getRootFolder() : DriveApp.getFolderById(e);
  console.log( ' da: ', da );
  var folders = da.getFolders();
//  console.log('folders.length: ', folders.length );  // undefined
  var files = da.getFiles();
//  console.log('files.length: ', files.length );  // undefined
  
  while (folders.hasNext()) {
    var folder = folders.next();
//      console.log('push folder name: ', folder.getName() );
    data[e].files.push({name: folder.getName(), id: folder.getId(), mimeType: "folder"});
  }
  console.log('     # files after folders.hasNext: ', data[e].files.length );
  
  while (files.hasNext()) {
    var file = files.next();
//    console.log('file.getMimeType(): ', file.getMimeType());
    if ( file.getMimeType() === 'folder' )    {;
      // do not save any files
    }    else if ( file.getMimeType() === inMimeType )    {
//      console.log('push fileArr name: ', file.getName() );
      fileArr.push([file.getName(),file.getId(), file.getMimeType()]);
    } else if ( inMimeType === 'EVERYTHING' )  {
      fileArr.push([file.getName(),file.getId(), file.getMimeType()]);
    } 
  }  
  console.log('     # files after files.hasNext: ', data[e].files.length );
  
  let sorted = gasArraySort(fileArr, 0, true);
  let numFiles = sorted.length;
  console.log('# after sort: ;', numFiles );
  for ( i = 0 ; i < numFiles ; i++ )  {
//    console.log('pushing sorted[i][0]: ', sorted[i][0] );
    data[e].files.push({name: sorted[i][0], id: sorted[i][1], mimeType: sorted[i][2]});
  }
  
  console.log('     # files after both while loops: ', data[e].files.length );
  console.log('     # files after both while loops JSON.stringify(data): ');
  console.log('     ', JSON.stringify(data) );
  console.log('End getFiles');
  return data;
}

Question 1: I am confused why I would see the log 3 ("3 after successHandler(importData) .getFiles(")which is after the getFiles / successHandler(importData) which apparently failed. Is this a timing issue? Did the log 3 happen before the importData blew up?

Question 2: Why is all the data returned from getFiles not seen in importData?

aNewb
  • 188
  • 1
  • 12
  • At first, I deeply apologize that my sample script was not useful for your situation. I have a question. Can you provide the difference between your script and my sample script? Because when I tested my sample script, no error occurs. I apologize for this situation. – Tanaike Mar 10 '21 at 02:04
  • Your sample works wonderfully. My changed version fails. See 2 questions at the end of the post. https://docs.google.com/spreadsheets/d/1woBp6ZsnzRiRhI9Trh9mfCp9N7IKWllBXk-pG1uzaPw/edit?usp=sharing entire project – aNewb Mar 10 '21 at 15:26
  • Thank you for replying. I deeply apologize that the script that you changed my sample script doesn't work. And also, I have to apologize for my poor English skill. Unfortunately, from `My changed version fails.`, I cannot understand about the detail changes of your current script. In order to correctly understand about it, can I ask you about the detail of `My changed version fails.`? By this, I would like to confirm it. – Tanaike Mar 11 '21 at 00:44
  • I add mime type to the code so I could pull just spreadsheets or docs. I have added the code where the error is happening and my questions at the top of the question above. Tanaike - your English is wonderful. I teach English to adults. – aNewb Mar 11 '21 at 14:50
  • Thank you for replying. I have to apologize for my poor skill. I cannot understand about what you want to do from your current script. So can I ask you about the detail of your goal? – Tanaike Mar 12 '21 at 01:42
  • I want to specify a mime type to select from - not list everything. What happens between the basic function getFiles and the successHandler(importData) that can make data disappear or fail to be recognized? How can a console log coded after the successHandler appear when the successHandler has failed? I shared editable link to entire project earlier. There are two HTML screens: first select file type do you want, then your html with files listed and a button to select. – aNewb Mar 12 '21 at 20:55
  • Thank you for replying. I have to apologize for my poor English skill again. Unfortunately, from your replying, I cannot still understand about your goal. But I would like to try to understand it. When I could correctly understand it, I would like to think of the solution. I deeply apologize I cannot resolve your issue soon. – Tanaike Mar 13 '21 at 01:31
  • Too bad there are no line numbers in the code. I will put more explanation at the top of the original post. I am sure you can explain why the call to getFiles which shows data and has a successHandler of importData loses the data somehow. I am sure it is a trivial error on my part., – aNewb Mar 13 '21 at 02:19
  • Replacing this with https://stackoverflow.com/questions/66626162/gas-data-from-server-side-function-not-seen-in-successhandler-function-in-html same problem much smaller code. – aNewb Mar 14 '21 at 15:17
  • No solution on simpler example yet. google.script.run .withSuccessHandler(importData) .getFiles(rootfolderId, rootfolderId, mimeType ); I can see output in log from getFiles but importData sees null – aNewb Mar 18 '21 at 15:13
  • I found my error. When I sorted the files I put the entries into arrays instead of objects. The data going to the importData function was half an array of objects and half an array of arrays. Someone with more points please close this and thanks everyone. – aNewb Mar 27 '21 at 17:44

0 Answers0