Reputation: 637
I have two files, app.js
and sheets.js
. I would like to pass data from app.js
into sheets.js
, which calls the Google Sheets API, then returns a value once it finishes the api call in the readData()
function.
The problem is the following:
When I attempt to to return the value of response
in app.js
as Sheets.readData(data)
it returns as undefined. I believe something in the callback chain is not allowing the returned value from readData()
to be passed into readSheet()
and therefore returning as undefined
. Am I missing a callback in readSheet that can return the authorize()
result? Or am I missing a callback function somewhere else? Thank you.
// Load client secrets from a local file.
exports.readSheet = function(data, callback) {
let response = fs.readFile('client_secret.json', function processClientSecrets(err, content) {
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
// Authorize a client with the loaded credentials, then call the
// Google Sheets API.
authorize(JSON.parse(content), data), readData);
});
return response;
}
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
*
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, data, callback) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
var auth = new googleAuth();
var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, function(err, token) {
if (err) {
getNewToken(oauth2Client, callback);
} else {
oauth2Client.credentials = JSON.parse(token);
callback(oauth2Client, data);
}
});
}
function readData(auth, data) {
var sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
auth: auth,
spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
range: 'Class Data!A2:E',
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var rows = response.values;
if (rows.length == 0) {
console.log('No data found.');
} else {
/* Return value here
let data = data + 'hello world';
return data
*/
}
});
}
Upvotes: 0
Views: 212
Reputation: 191789
readData
runs asynchronously and depends on the completion of sheets.spreadsheets.values.get
which is asynchronous. There are several ways to handle this. The simplest in your case would be to pass a callback function to readData
:
function readData(auth, data, cb) {
/* your code here */
} else {
// successful response from sheets
cb(null, response);
}
});
}
Then you would have to update your call to authorize
to call callback
instead of just readData
:
authorize(JSON.parse(content), data, (auth, data) => readData(auth, data, callback);
However from what I can tell, the Google APIs support promises. It would be much easier / cleaner to write the code to use promises. You can use the mz
library for fs
methods that have promise support.
// NOTE! This is a simple example with no error handling
exports.readSheet = async function (data) {
const content = fs.readFile('client_secret.json');
const [auth, data] = authorize(JSON.parse(content), data);
return readData(auth, data);
}
async function authorize(credentials, data, callback) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
var auth = new googleAuth();
var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
const token = await fs.readFile(TOKEN_PATH);
oauth2Client.credentials = JSON.parse(token);
return [oauth2Client, data];
}
async function readData(auth, data) {
const sheets = google.sheets('v4');
return sheets.spreadsheets.values.get({
auth: auth,
spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
range: 'Class Data!A2:E',
});
}
Upvotes: 0