简体   繁体   中英

Nodejs exports.module How to export Variable to other Script

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:

  1. the 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.
  2. the array for waiting callbacks that will be triggered upon load ( 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM