Why am I getting an undefined value when calling these scripts in Google App Maker? - google-apps-script

I do not understand why when I am calling a ServerScript method from a ClientScript method, I am getting a value of undefined.
ClientScript:
function clientScript() {
var message;
message = google.script.run.test();
console.log("Message: " + message);
}
ServerScript:
function serverScript() {
return "hello";
}
I expected the console to print: Message: hello. However, I am getting this printed to my console: Message: undefined. Why am I getting an undefined value in my ClientScript method when I am returning a defined value in my ServerScript method? Thank you!

Because server calls are asynchronous. In order to handle server response you need to pass callback. Here is a snippet from Apps Script docs:
function onSuccess(numUnread) {
console.log(numUnread);
}
google.script.run.withSuccessHandler(onSuccess)
.getUnreadEmails();
Just in case AMs docs interpretation of the same thing - https://developers.google.com/appmaker/scripting/client#call_a_server_script

Related

react native- json parsing (cant parse json object in my code)

Here is my code. In this I got x but when I try to parsing x for getting object of x 'isloggedin' it gives error. what should I do wrong tell me if you understand my problem.
componentDidMount() {
this.onLoad();
}
onLoad = async () => {
try {
var walletdata = await AsyncStorage.getItem('wallet');
this.setState({x: JSON.parse(walletdata)})
this.setState({y: JSON.stringify(this.state.x)})
console.log("output: "+ this.state.y);
console.log("output y:"+JSON.parse(this.state.y.isloggedIn));
}catch(error){
console.log("error: "+error);
}
}
error: SyntaxError: JSON Parse error: Unexpected identifier "undefined"
Probably is because 'wallet' key has undefined value in the caché storage. You should check first the value (right after getting the item from the storage) and if it's undefined then you have to set it first.
Probably you need to wait for the first setState function to finish, So that you can get access to it in second call.
In short, It will take some time for setting your value in State and you are trying to access it before updating the state. So try to access the values in the callback of setState function.
Instead of this,
this.setState({x: JSON.parse(walletdata)})
this.setState({y: JSON.stringify(this.state.x)})
console.log("output: "+ this.state.y);
console.log("output y:"+JSON.parse(this.state.y.isloggedIn));
You can use this:
this.setState({x: JSON.parse(walletdata),y: JSON.stringify(walletdata.x)},()=>{
console.log("output: "+ this.state.y);
console.log("output y:"+JSON.parse(this.state.y.isloggedIn));
});
I have solved my problem. Thank you for your answers. below is how could I solved my question.
try {
var walletdata = await AsyncStorage.getItem('wallet');
this.setState({wallet: JSON.stringify(JSON.parse(walletdata))})
this.setState({isLoggedin:JSON.parse
(this.state.wallet).isLoggedin});
console.log(this.state.isLoggedin);
}catch(error){
console.log("error: "+error);
}

HTTP failure callback for UrlFetchApp.fetch() in gmail addon

I would like to write a callback when a HTTP requests fails. How do I chain it to UrlFetchApp.fetch()?
Please refer to the HTTP request below.
// Make a GET request.
UrlFetchApp.fetch('http://www.google.com/');
Please note that the fetch function is synchronous. It does not provide a callback parameter and does not return a promise.
An approach to catching exceptions is possible through the UrlFetchApp.fetch(url, params) function. You can pass the muteHttpExceptions parameter into the params location of the function call. That way you can inspect the response code yourself and respond appropriately. Documentation: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl-params
UrlFetchApp.fetch('http://www.google.com/', {muteHttpExceptions: true});
muteHttpExceptions (Boolean) if this is set to true, the fetch will not
throw an exception if the response code indicates failure, and will
instead return the HTTPResponse (default: false)
An alternative would be a simple try/catch statement. I imagine you could log the error or respond appropriately.
try {
UrlFetchApp.fetch('http://www.google.com/');
}
catch(e) {
// e contains error response
}

Can't pass values to HtmlService

Here is the function I am using to get all the active values on my spreadsheet:
function getAllValuesInSheet(){
var values = SpreadsheetApp.getActiveSpreadsheet().getDataRange().getValues();
Logger.log(values);
return values;
}
This returns an 2D Array of my values.
In my HtmlService I have:
<script>
function onSuccess(values) {
console.log("ran");
console.log(values);
}
function populate(){
google.script.run.withSuccessHandler(onSuccess).getAllValuesInSheet();
}
</script>
<script>
// Using the "load" event to execute the function "populate"
window.addEventListener('load', populate);
</script>
I get an error Uncaught ScriptError: The script completed but the returned value is not a supported return type.
I have functions similar to this one that work perfectly fine. I wonder if the data is too large to pass? It's not that big it's under 500 cells.
Why am I getting this error? How can I fix this? I am trying to load all my spreadsheet data to my HtmlService. Is this a bad practice for small data sets? Should I make ajax calls back and forth instead?
Try converting the array to a json format with the function JSON.stringify(object) so the array is easier to treat.
your code would be like:
return JSON.stringify(values);
Check if this doesn't work for you.
The reason that Gerardo's answer works is because it ensures that your server-side function returns a String, which is a JavaScript primitive.
Your original request would fail if any of the array contents consisted of unsupported types such as Date objects.
Source: HTML Service: Communicate with Server Functions

What does d3js.csv.get() do?

I'm learning d3js. I came across an example for extracting CSV values here. I'm quoting the code:
d3.csv("path/to/file.csv")
.row(function(d) { return {key: d.key, value: +d.value}; })
.get(function(error, rows) { console.log(rows); });
From the description, I get that .row() is the accessor here. But the role of the .get() is not clear to me. When is this function called, and for what purpose ? Thanks.
The .get() is a function of the underlying AJAX request -- it sends the request and establishes the callback. From the documentation:
xhr.get([callback])
Issues this request using the GET method. If a callback is specified, it will be invoked asynchronously when the request is done or errors; the callback is invoked with two arguments: the error, if any, and the response value.

Call to realtime.loadAppDataDocument fails when realtime.load works?

After calling realtime.loadAppDataDocument I receive the error:
XMLHttpRequest cannot load https://drive.google.com/load?
access_token=ya29.AHES6ZRoDqY0PmpHlbUjniB8wIl… Kzw
&id=1xAp1SMlamIfjnUGO9pDwfNF5IphdtnZsCw36KalJss27wy00LJ-rCN9MpcHMx408Xg.
Origin http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
However if I call realtime.load with a fileid it works. See code extract below
if (fileId === null) {
// this call fails
gapi.drive.realtime.loadAppDataDocument(onFileLoaded, initializeStorageModel, handleErrors);
} else {
// this call succeeds
gapi.drive.realtime.load(fileId, onFileLoaded, initializeStorageModel, handleErrors);
}
Variables being used before this point (passed to google for the access token):
LOAD_APIS = 'auth:client,drive-realtime,drive-share';
SCOPE = [
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.file'
];
LOAD_CLIENT_APIS = ['drive', 'v2'];
Does anyone know how to get the method realtime.loadAppDataDocument to work?
Update: I think the request may be actually receiving a 401 response (but because the CORS header isn't sent with the 401 response the Access-Control-Allow-Origin error is called)
Google pushed some changes to the Realtime API which has fixed the problem.