I'm moving some python code to Node JS.
In python, I have connection to Google Sheet API v4 with a self.service = BuildService().build('sheets') function which I can initiate whenever I need connection to Google sheets.
I got problems when I move to Node JS because the example code on Google's quickstart is using a async function. I can get the example to work, but I can't use it the same way I have it in Python, in that I can't get the value out of the function. I have tried to use global variables inside the Node JS function to return to me the service build or even the result, but when I make a request to it, it always gives me a promise. I can use await but I always have to wrap it inside a function and it seems like the result can't come out of the function because it is async.
Here is what the code flow looks like in python and in Node
Python:
service = BuildService().build('sheets')
key = 'xxxxxxxx'
ranges = ['test!A1']
res = service.spreadsheets().values().get(spreadsheetId=key, range=ranges).execute()
in Node JS
var sheets = authorize() // --> sheets {context: {…}, spreadsheets: Resource$Spreadsheets}
var id = 'xxxxxxx'
var ranges = ['test!A1']
const res = sheets.spreadsheets.values.batchGet({
spreadsheetId: id,
ranges: ranges_ar, valueRenderOption: "FORMATTED_VALUE"}
)
// res --> Promise
// Promise {[[PromiseState]]: 'pending', [[PromiseResult]]: undefined, Symbol(async_id_symbol): 16, Symbol(trigger_async_id_symbol): 1}
I use authorize().then(listMajors).catch(console.error); like in the quickstart example to get it work, but can't get the result to come out of the function. Wrapping it does no good, because it then can't come out of the wrapper.
Is there a way to make a connection to Google API V4 without using async? I want to rewrite my python code in Node JS using the same flow. Is this possible? Or does going over to Node JS means I have rearchitect all of my code?
full script, by Tanaike's suggestion, not working yet:
// https://developers.google.com/sheets/api/quickstart/nodejs
const fs = require('fs');
const path = require('path');
const process = require('process');
const {authenticate} = require('@google-cloud/local-auth');
const {google} = require('googleapis');
const request = require("sync-request");
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];
const CREDENTIALS_PATH = 'xxxxxx'
const TOKEN_PATH = 'xxxxxxxx';
function loadSavedCredentialsIfExist() {
try {
const content = fs.readFile(TOKEN_PATH);
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}
function saveCredentials(client) {
const content = fs.readFile(CREDENTIALS_PATH);
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: 'authorized_user',
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
fs.writeFile(TOKEN_PATH, payload);
}
function authorize() {
let client = loadSavedCredentialsIfExist();
if (client) {
} else{
client = authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client.credentials) {
saveCredentials(client);
}
}
const sheets = google.sheets({version: 'v4', client});
return sheets
}
var sheets = authorize()
var id = 'xxxxxxx'
var ranges= ['Data!A2:E10']
const accessToken = sheets.context._options.auth.credentials.access_token;
const query = new URLSearchParams({ ranges, valueRenderOption: "FORMATTED_VALUE" }).toString();
const url = `https://sheets.googleapis.com/v4/spreadsheets/${id}/values:batchGet?${query}`;
const resObj = request("GET", url, { headers: { Authorization: `Bearer ${accessToken}` }});
const res = resObj.getBody("utf8");
console.log(res);
You should not be using this in a production application.. So, in the current stage, I think that using async/await might be better. How about this? But, I'm not sure about your expected direction of your goal. So, I posted this as a comment. I apologize for this.