my goal is to get a list of files from a google drive folder and its subfolders as json string. so i can then use express to expose it as an API endpoint that other applications can connect to it.
the code is working. i get everything i want, but i do not know how to export my data variable to app.js
// get-filelist.js
var GoogleTokenProvider = require("refresh-token").GoogleTokenProvider,
request = require('request'),
async = require('async'),
data
const CLIENT_ID = "514...p24.apps.googleusercontent.com";
const CLIENT_SECRET = "VQs...VgF";
const REFRESH_TOKEN = "1/Fr...MdQ"; // get it from: https://developers.google.com/oauthplayground/
const FOLDER_ID = '0Bw...RXM';
async.waterfall([
//-----------------------------
// Obtain a new access token
//-----------------------------
function(callback) {
var tokenProvider = new GoogleTokenProvider({
'refresh_token': REFRESH_TOKEN,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
});
tokenProvider.getToken(callback);
},
//-----------------------------
// connect to google drive, look for the folder (FOLDER_ID) and list its content inclusive files inside subfolders.
// return a list of those files with its Title, Description, and view Url.
//-----------------------------
function(accessToken, callback) {
// access token is here
console.log(accessToken);
// function for token to connect to google api
var googleapis = require('./lib/googleapis.js');
var auth = new googleapis.OAuth2Client();
auth.setCredentials({
access_token: accessToken
});
googleapis.discover('drive', 'v2').execute(function(err, client) {
getFiles()
function getFiles(callback) {
retrieveAllFilesInFolder(FOLDER_ID, 'root' ,getFilesInfo);
}
function retrieveAllFilesInFolder(folderId, folderName, callback) {
var retrievePageOfChildren = function (request, result) {
request.execute(function (err, resp) {
result = result.concat(resp.items);
var nextPageToken = resp.nextPageToken;
if (nextPageToken) {
request = client.drive.children.list({
'folderId': folderId,
'pageToken': nextPageToken
}).withAuthClient(auth);
retrievePageOfChildren(request, result);
} else {
callback(result, folderName);
}
});
}
var initialRequest = client.drive.children.list({
'folderId': folderId
}).withAuthClient(auth);
retrievePageOfChildren(initialRequest, []);
}
function getFilesInfo(result, folderName) {
result.forEach(function (object) {
request = client.drive.files.get({
'fileId': object.id
}).withAuthClient(auth);
request.execute(function (err, resp) {
// if it's a folder lets get it's contents
if(resp.mimeType === "application/vnd.google-apps.folder"){
retrieveAllFilesInFolder(resp.id, resp.title, getFilesInfo);
}else{
/*if(!resp.hasOwnProperty(folderName)){
console.log(resp.mimeType);
}*/
url = "http://drive.google.com/uc?export=view&id="+ resp.id;
html = '<img src="' + url+ '"/>';
// here do stuff to get it to json
data = JSON.stringify({ title : resp.title, description : resp.description, url : url});
//console.log(data);
//console.log(resp.title);console.log(resp.description);console.log(url);
//.....
}
});
});
}
});
}
]);
// export the file list as json string to expose as an API endpoint
console.log('my data: ' + data);
exports.files = function() { return data; };
and in my app.js i use this
// app.js
var jsonData = require('./get-filelist');
console.log('output: ' + jsonData.files());
the data variable in app.js doesnt contain any data, while checking the output inside the function getFilesInfo() is working.
so, how to make my data variable accessible in other scripts?
You've got a problem with sync/async behavior.
app.js should be aware when to call the files() function exported from get-filelist
. The code you've got there calls the files() function immediately after requiring the get-filelist
module. At that moment the data
variable is still empty.
Best solution would be to provide the files() function with a callback that will trigger once you've loaded the data
variable.
Of course, you will need some extras:
loaded
flag so that you know whether to trigger the callback immediately (if data
is already loaded) or postpone the trigger once the load is done. callbacks
). // get-filelist.js
var GoogleTokenProvider = require("refresh-token").GoogleTokenProvider,
request = require('request'),
async = require('async'),
loaded = false, //loaded? Initially false
callbacks = [], //callbacks waiting for load to finish
data = [];
const CLIENT_ID = "514...p24.apps.googleusercontent.com";
const CLIENT_SECRET = "VQs...VgF";
const REFRESH_TOKEN = "1/Fr...MdQ"; // get it from: https://developers.google.com/oauthplayground/
const FOLDER_ID = '0Bw...RXM';
async.waterfall([
//-----------------------------
// Obtain a new access token
//-----------------------------
function(callback) {
var tokenProvider = new GoogleTokenProvider({
'refresh_token': REFRESH_TOKEN,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
});
tokenProvider.getToken(callback);
},
//-----------------------------
// connect to google drive, look for the folder (FOLDER_ID) and list its content inclusive files inside subfolders.
// return a list of those files with its Title, Description, and view Url.
//-----------------------------
function(accessToken, callback) {
// access token is here
console.log(accessToken);
// function for token to connect to google api
var googleapis = require('./lib/googleapis.js');
var auth = new googleapis.OAuth2Client();
auth.setCredentials({
access_token: accessToken
});
googleapis.discover('drive', 'v2').execute(function(err, client) {
getFiles()
function getFiles(callback) {
retrieveAllFilesInFolder(FOLDER_ID, 'root' ,getFilesInfo);
}
function retrieveAllFilesInFolder(folderId, folderName, callback) {
var retrievePageOfChildren = function (request, result) {
request.execute(function (err, resp) {
result = result.concat(resp.items);
var nextPageToken = resp.nextPageToken;
if (nextPageToken) {
request = client.drive.children.list({
'folderId': folderId,
'pageToken': nextPageToken
}).withAuthClient(auth);
retrievePageOfChildren(request, result);
} else {
callback(result, folderName);
}
});
}
var initialRequest = client.drive.children.list({
'folderId': folderId
}).withAuthClient(auth);
retrievePageOfChildren(initialRequest, []);
}
function getFilesInfo(result, folderName) {
data = []; //data is actually an array
result.forEach(function (object) {
request = client.drive.files.get({
'fileId': object.id
}).withAuthClient(auth);
request.execute(function (err, resp) {
// if it's a folder lets get it's contents
if(resp.mimeType === "application/vnd.google-apps.folder"){
retrieveAllFilesInFolder(resp.id, resp.title, getFilesInfo);
}else{
/*if(!resp.hasOwnProperty(folderName)){
console.log(resp.mimeType);
}*/
url = "http://drive.google.com/uc?export=view&id="+ resp.id;
html = '<img src="' + url+ '"/>';
// here do stuff to get it to json
data.push(JSON.stringify({ title : resp.title, description : resp.description, url : url}));
//console.log(resp.title);console.log(resp.description);console.log(url);
//.....
}
});
});
//console.log(data); //now, that the array is full
//loaded is true
loaded = true;
//trigger all the waiting callbacks
while(callbacks.length){
callbacks.shift()(data);
}
}
});
}
]);
// export the file list as json string to expose as an API endpoint
console.log('my data: ' + data);
exports.files = function(callback) {
if(loaded){
callback(data);
return;
}
callbacks.push(callback);
};
Now the app.js behavior needs to change:
// app.js
var jsonData = require('./get-filelist');
jsonData.files(function(data){
console.log('output: ' + data);
});
/* a much more elegant way:
jsonData.files(console.log.bind(console,'output:'));
//which is actually equivalent to
jsonData.files(function(data){
console.log('output: ',data); //without the string concatenation
});
*/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.