admin管理员组

文章数量:1302958

I have the following published webapp with code.gs

var queryString

function doGet(e) {
  queryString = e.queryString  

  //logger only works if the return value is mented out
  Logger.log(queryString)

  return HtmlService.createHtmlOutputFromFile('index.html')
}

function getQueryString() {
  // this prints "a=1" on the html
  // return "a=1"

  // this prints "undefined" on the html
  return queryString
}

and index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(queryString) {
        var div = document.getElementById('output');
        div.innerHTML = queryString;
      }
    </script>
  </head>
  <body>
    <button type="button" onclick="javascript:google.script.run.withSuccessHandler(onSuccess).getQueryString();">show query string</button>
    <div id="output"></div>
  </body>
</html>

When the button is pressed, the webpage looks as follows

However, I expect the display of the query string. The value of the query string is saved to the global variable queryString during the call of doGet(). Once the user presses the button, the server side function getQueryString should provide the client side html page with the value of the global variable queryString, but it doesn't. It seems like a new context is generated everytime a server side function is called with newly initialized variables

The use of PropertiesService seems overkill to me. What is the best way to solve that problem?

I have the following published webapp with code.gs

var queryString

function doGet(e) {
  queryString = e.queryString  

  //logger only works if the return value is mented out
  Logger.log(queryString)

  return HtmlService.createHtmlOutputFromFile('index.html')
}

function getQueryString() {
  // this prints "a=1" on the html
  // return "a=1"

  // this prints "undefined" on the html
  return queryString
}

and index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(queryString) {
        var div = document.getElementById('output');
        div.innerHTML = queryString;
      }
    </script>
  </head>
  <body>
    <button type="button" onclick="javascript:google.script.run.withSuccessHandler(onSuccess).getQueryString();">show query string</button>
    <div id="output"></div>
  </body>
</html>

When the button is pressed, the webpage looks as follows

However, I expect the display of the query string. The value of the query string is saved to the global variable queryString during the call of doGet(). Once the user presses the button, the server side function getQueryString should provide the client side html page with the value of the global variable queryString, but it doesn't. It seems like a new context is generated everytime a server side function is called with newly initialized variables

The use of PropertiesService seems overkill to me. What is the best way to solve that problem?

Share Improve this question edited Jan 12, 2019 at 16:11 TheMaster 50.8k7 gold badges69 silver badges99 bronze badges asked Apr 8, 2016 at 20:53 kusikusi 1872 silver badges7 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 8

A value assigned to a Global variable doesn't persist after the stack has pleted. If the function that is using a global variable doesn't call another function, then there are no other functions in the stack. It's important to know that the value of a global variable will maintain it's value from one function call to another in the same stack. So, you can use a global variable to make a value available to other functions, instead of passing the value between functions. But, you do need to understand the dangers of using a global variable. Many people are vehemently opposed to the use of global variables at all. But I'm not trying to answer why you should or shouldn't use a global variable, or if you should under what conditions.

I'm stating that you should use Properties Service in your situation.

If the initial function that was called, calls another function, and then the second function calls a third function, the global variable will retain it's value from the first function to the second function and the second function to the third function, etc, but once all the functions in the chain (stack) have pleted, the global variable's value is gone.

If you need to save a value from one instance of the code running, and then retrieve that value from another instance of the code running, then you can use either Cache Service or Properties Service.

Cache Service is timed. Storage only lasts for a certain amount of time. Cache Service is timed with a default time that can be overridden with a setting.

Properties Service is permanent. A value stored in Properties Service should never loose it's value unless you intentionally delete it or change it. Properties Service storage is bound to the document, user, or script. If you use a document property, and then delete the document, then the stored value will also be gone.

So, unless you want to save the query string to a Drive file, Cache Service and Properties Service are your only available options. Sounds like you may want to look into Cache Service, and just make sure you consider how long it should stay in memory before the value "times out".

Although the previous answer is correct, I believe that in the spirit of the question, this might be useful.

  • You can push/replace/retrieve state client side using google.script.history and google.script.url. This is similar to typical JavaScript history.pushState, but with extra restrictions.

Client Side Working Sample:

(Using google.script.url to retrieve querystring)

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess() {
        var div = document.getElementById('output');
        google.script.url.getLocation(function(location){
        var obj = location.parameter;
        div.innerHTML= Object.keys(obj).map(e=>e+'='+obj[e]).join('&');
        }); 
      }
    </script>
  </head>
  <body>
    <button type="button" onclick="onSuccess();">show query string</button>
    <div id="output"></div>
  </body>
</html>

References:

  • WebApps browing history guide
  • Javascript History API

本文标签: javascriptWhere to save states in google apps script with HtmlServiceStack Overflow