Async.parallel()与谷歌api的节点js

时间:2018-03-19 06:53:09

标签: node.js asynchronous google-calendar-api

我在async.parallel内放置代码(用于从谷歌日历中获取假期)并在执行后获得结果。

但async结果已经返回,甚至async.parallel中的代码还没有完成。

以下是代码:

var ph_holiday = false;
var test_var = false;

async.parallel({
        test: function(callback) {
            //============ This code is from google calendar tutorial========  
            // If modifying these scopes, delete your previously saved credentials
            // at ~/.credentials/calendar-nodejs-quickstart.json
            var SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
            var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
                process.env.USERPROFILE) + '/.credentials/';
            var TOKEN_PATH = TOKEN_DIR + 'calendar-nodejs-quickstart.json';

            // Load client secrets from a local file.
            fs.readFile('services/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 Calendar API.
                authorize(JSON.parse(content), listEvents);
            });

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

            /**
             * Get and store new token after prompting for user authorization, and then
             * execute the given callback with the authorized OAuth2 client.
             *
             * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
             * @param {getEventsCallback} callback The callback to call with the authorized
             *     client.
             */
            function getNewToken(oauth2Client, callback) {
                var authUrl = oauth2Client.generateAuthUrl({
                access_type: 'offline',
                scope: SCOPES
                });
                console.log('Authorize this app by visiting this url: ', authUrl);
                var rl = readline.createInterface({
                input: process.stdin,
                output: process.stdout
                });
                rl.question('Enter the code from that page here: ', function(code) {
                rl.close();
                oauth2Client.getToken(code, function(err, token) {
                    if (err) {
                    console.log('Error while trying to retrieve access token', err);
                    return;
                    }
                    oauth2Client.credentials = token;
                    storeToken(token);
                    callback(oauth2Client);
                });
                });
            }

            /**
             * Store token to disk be used in later program executions.
             *
             * @param {Object} token The token to store to disk.
             */
            function storeToken(token) {
                try {
                fs.mkdirSync(TOKEN_DIR);
                } catch (err) {
                if (err.code != 'EEXIST') {
                    throw err;
                }
                }
                fs.writeFile(TOKEN_PATH, JSON.stringify(token));
                console.log('Token stored to ' + TOKEN_PATH);
            }

            /**
             * Lists the next 10 events on the user's primary calendar.
             *
             * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
             */
            function listEvents(auth) {
                var calendar = google.calendar('v3');
                // List of events for Philippines
                calendar.events.list({
                auth: auth,
                calendarId: encodeURIComponent('en.philippines#holiday@group.v.calendar.google.com'),
                timeMin: (new Date()).toISOString(),
                maxResults: 1,
                singleEvents: true,
                orderBy: 'startTime',
                }, function(err, response) {
                if (err) {
                    console.log('The API returned an error: ' + err);
                    return;
                }
                var events = response.items;
                if (events.length == 0) {
                    console.log('No upcoming events found.');
                } else {
                    //console.log('Upcoming 10 events:');
                    for (var i = 0; i < events.length; i++) {
                        var event = events[i];
                        var start = event.start.dateTime || event.start.date;
                        //console.log('%s - %s', start, event.summary);

                        // My custom code | check if today is holiday based from google calendar
                        var today = moment().format("YYYY-MM-DD");
                        if (today == event.start.date) {
                            console.log("Today is holiday. " + event.start.date);
                            ph_holiday = true;
                            //console.log(ph_holiday);
                        }
                    }
                }
                });

            }

            callback(null, ph_holiday);
        },

        test2: function(callback) {
            test_var = true;
            callback(null, test_var);
        }
    }, function(err, results) {
        // expected output is 'true' but the result is false
        console.log("ph holiday: " + results.test[0]);
        // this out correctly
        console.log("test2: " + results.test2[1]);
    });

我不知道这段代码有什么问题。 提前感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

Javascript是asysncronous,这意味着当您调用网络请求时正如您正在调用google calendar v3 api的函数listEvents,从谷歌获取数据。在调用语句callback(null, ph_holiday)之前,Javascript不会等待响应函数被调用。因此,在调用回调函数之前,变量ph_holiday不会设置为true。尝试在当前代码中设置console.log以查看代码如何流动。您可以将代码更新为如下所示,它应该可以正常工作

function listEvents(auth) {
    var ph_holiday = false;
    var calendar = google.calendar('v3');
    // List of events for Philippines
    calendar.events.list({
    auth: auth,
    calendarId: encodeURIComponent('en.philippines#holiday@group.v.calendar.google.com'),
    timeMin: (new Date()).toISOString(),
    maxResults: 1,
    singleEvents: true,
    orderBy: 'startTime',
    }, function(err, response) {
        if (err) {
            console.log('The API returned an error: ' + err);
            return;
        }
        var events = response.items;
        if (events.length == 0) {
            console.log('No upcoming events found.');
        } else {
            //console.log('Upcoming 10 events:');
            for (var i = 0; i < events.length; i++) {
            var event = events[i];
            var start = event.start.dateTime || event.start.date;
            //console.log('%s - %s', start, event.summary);

            // My custom code | check if today is holiday based from google calendar
            var today = moment().format("YYYY-MM-DD");
            if (today == event.start.date) {
                console.log("Today is holiday. " + event.start.date);
                ph_holiday = true;
                //console.log(ph_holiday);
            }
        }
        callback(null, ph_holiday);
    }
});
}

答案 1 :(得分:0)

  

但async结果已经返回,甚至async.parallel中的代码还没有完成。

Async.parallel()会返回false,因为您在callback()之外呼叫listEvents()。只有在完成提取假期后才需要致电callback()

进行此更改,

'use strict';

var ph_holiday = false;
var test_var = false;

async.parallel({
  test: function (callback) {

    var SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
    var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE) + '/.credentials/';
    var TOKEN_PATH = TOKEN_DIR + 'calendar-nodejs-quickstart.json';

    fs.readFile('services/client_secret.json', function processClientSecrets(err, content) {
      if (err) {
        console.log('Error loading client secret file: ' + err);
        return;
      }
      authorize(JSON.parse(content), listEvents);
    });

    function authorize(credentials, callback) { ... }

    function getNewToken(oauth2Client, callback) { ... }

    function storeToken(token) { ... }

    function listEvents(auth) {
      var calendar = google.calendar('v3');
      calendar.events.list({
        auth: auth,
        calendarId: encodeURIComponent('en.philippines#holiday@group.v.calendar.google.com'),
        timeMin: (new Date()).toISOString(),
        maxResults: 1,
        singleEvents: true,
        orderBy: 'startTime',
      }, function (err, response) {
        if (err) {
          callback(err, null); //CHANGE HERE
        }

        // Your code here

        callback(null, ph_holiday); //CHANGE HERE
      });

    }

  },
  test2: function (callback) {
    test_var = true;
    callback(null, test_var);
  }
}, function (err, results) {
  if (err) {
    return console.log('The API returned an error: ', err);
  }
  console.log("ph holiday: " + results.test);
  console.log("test2: " + results.test2);
});