Nodejs exports.module如何将Variable导出到其他Script

时间:2014-09-21 10:58:48

标签: javascript node.js google-api google-drive-api

我的目标是从google驱动器文件夹及其子文件夹中获取文件列表作为json字符串。所以我可以使用express将它暴露为其他应用程序可以连接到它的API端点。

代码正常运行。我得到了我想要的一切,但我不知道如何将我的数据变量导出到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; };

在我的app.js中我用这个

// app.js
var jsonData = require('./get-filelist');

console.log('output: ' + jsonData.files());

app.js中的数据变量不包含任何数据,同时检查函数getFilesInfo()内的输出是否有效。

那么,如何在其他脚本中访问我的数据变量?

1 个答案:

答案 0 :(得分:0)

您遇到同步/异步行为问题。

app.js应该知道何时来调用从get-filelist导出的files()函数。您需要get-filelist模块后,您所在的代码会立即调用files()函数。那时data变量仍为空。

最佳解决方案是为files()函数提供一个回调,该回调将在您加载data变量后触发。

当然,你需要一些额外的东西:

  1. loaded标志,以便您知道是否立即触发回调(如果已加载data)或在加载完成后推迟触发。
  2. 用于等待将在加载时触发的回调的数组(callbacks)。
  3.     // 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);
    };
    

    现在app.js的行为需要改变:

    // 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
    });
    */