用Node,Express和google Analytics API在callback地狱中丢失

我在这里是初学者,所以我会尽我所能地揭露我的问题。 我试图在服务器端调用Google AnalyticsAPI,以在客户端显示一些数据,并使用d3和react。 这是我的脚本来调用GA API:

var google = require ("googleapis"); var key = require ('./client_id.json'); const VIEW_ID = 'ga:80820965'; let jwtClient = new google.auth.JWT( key.client_email, null, key.private_key, ['https://www.googleapis.com/auth/analytics.readonly'], null ); jwtClient.authorize(function (err, tokens) { if (err) { console.log(err); return; } let analytics = google.analytics('v3'); queryData(analytics); }); var queryData = function(analytics) { analytics.data.ga.get({ 'auth': jwtClient, 'ids': VIEW_ID, 'metrics': 'ga:uniquePageviews', 'dimensions': 'ga:pagePath', 'start-date': '30daysAgo', 'end-date': 'yesterday', 'sort': '-ga:uniquePageviews', 'max-results': 10, }, function (err, response) { if (err) { console.log(err); return; } console.log(JSON.stringify(response, null, 4)); }); } module.exports = { queryData }; 

当我独立地调用这个脚本时,一切都很好,但是当我用整个项目调用它的时候,我得到了下面的错误:

 [1] analytics.data.ga.get({ [1] ^ [1] [1] TypeError: Cannot read property 'data' of undefined 

从我所了解的data是不确定的,因为analytics是不确定的。 而analytics是不确定的,因为这个调用:

  jwtClient.authorize(function (err, tokens) { if (err) { console.log(err); return; } let analytics = google.analytics('v3'); data = queryData(analytics); }); 

是一个asynchronous调用。 我猜测client_id被加载的时间。

那么我怎么写这个脚本,以便queryData只在这个部分运行:

 let analytics = google.analytics('v3'); data = queryData(analytics); 

准备好了 ?

我希望我的问题很清楚,对你有意义。 我读过有关asynchronous/等待模块。 但是我不能使用它我自己。

编辑#1:我需要使用这样的东西,但我不知道如何

 module.exports = {queryData: function (err, req, res, next) { next(); }}; 

您将analytics定义为本地variables:

 jwtClient.authorize(function (err, tokens) { if (err) { console.log(err); return; } let analytics = google.analytics('v3'); queryData(analytics); }); 

然后期待它在您的导出中的queryData(analytics)中可用。

你可以做的是在一个promise中parsing你的authorize调用(因为在第一次初始化的时候会有一个竞争条件,所以你可以把它包装在一个promise中并等待它parsing,然后才能调用queryData )。 像这样的东西:

 var google = require ("googleapis"); var key = require ('./client_id.json'); const Promise = require('bluebird'); var authorizationPromise; const VIEW_ID = 'ga:80820965'; let jwtClient = new google.auth.JWT( key.client_email, null, key.private_key, ['https://www.googleapis.com/auth/analytics.readonly'], null ); authorizationPromise = Promise.promisify(jwtClient.authorize)() .then(function (err, tokens) { if (err) { throw new Error(err); } return google.analytics('v3'); }) .catch(function(err) { console.log(err); }); var queryData = function() { authorizationPromise.then(function(analytics) { analytics.data.ga.get({ 'auth': jwtClient, 'ids': VIEW_ID, 'metrics': 'ga:uniquePageviews', 'dimensions': 'ga:pagePath', 'start-date': '30daysAgo', 'end-date': 'yesterday', 'sort': '-ga:uniquePageviews', 'max-results': 10, }, function (err, response) { if (err) { console.log(err); return; } console.log(JSON.stringify(response, null, 4)); }); }); }; module.exports = { queryData }; 

我不确定jwtClient.authorize是否提供了一个承诺API,所以我只是使用蓝鸟 “promisified”它。