迷失在回调地狱与Node, Express和谷歌分析API

Lost in callback hell with Node, Express and google Analytics API

本文关键字:谷歌 API Express 回调 地狱 Node 迷失      更新时间:2023-09-26

我是新手,所以我会尽量以最好的方式暴露我的问题。我试图调用谷歌分析API在服务器端显示一些数据在客户端与反应和d3。下面是我调用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);
    });

是一个异步调用。我猜是加载client_id的时间。

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

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

准备好了吗?

我希望我的问题对你来说是清楚和有意义的。我读过async/await模块。但是我自己不会用。

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

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

您在这里将analytics定义为局部变量:

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

然后期望它在queryData(analytics)中可用。

你可以做的是在一个promise中解析你的authorize调用(因为当它第一次初始化时会有一个竞争条件,所以你可以把它包装在一个promise中,等待它在能够调用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,所以我只是"承诺"它使用蓝鸟。