Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用服务帐户访问Google工作表时未定义回调_Javascript_Node.js_Google Api_Google Sheets Api_Google Api Nodejs Client - Fatal编程技术网

Javascript 使用服务帐户访问Google工作表时未定义回调

Javascript 使用服务帐户访问Google工作表时未定义回调,javascript,node.js,google-api,google-sheets-api,google-api-nodejs-client,Javascript,Node.js,Google Api,Google Sheets Api,Google Api Nodejs Client,我正在尝试从一个公开的谷歌表格中获取数据。此工作表对任何人都具有只读访问权限。我用这个。我使用一个服务帐户来验证请求,因为我使用同一个服务帐户访问另一个无法公开的工作表 代码运行正常,但当我将Node.js客户端更新到最新版本时,它开始给我带来奇怪的错误。我已经为这个错误创建了一个缩小的示例,下面是代码- /*eslint-disable no-console */ const { promisify } = require('util'); const GoogleAuth = require

我正在尝试从一个公开的谷歌表格中获取数据。此工作表对任何人都具有只读访问权限。我用这个。我使用一个服务帐户来验证请求,因为我使用同一个服务帐户访问另一个无法公开的工作表

代码运行正常,但当我将Node.js客户端更新到最新版本时,它开始给我带来奇怪的错误。我已经为这个错误创建了一个缩小的示例,下面是代码-

/*eslint-disable no-console */
const { promisify } = require('util');
const GoogleAuth = require('google-auth-library');
const { google } = require('googleapis');
const googleAuth = new GoogleAuth();

const sheets = google.sheets('v4');
sheets.spreadsheets.values.getAsync = promisify(sheets.spreadsheets.values.get);

async function authorizeWithServiceAccount(serviceAccountKey, scopes) {
  try {
    let authClient = await authorize(serviceAccountKey, scopes);
    return authClient;
  } catch (err) {
    console.error(err);
    throw err;
  }
}

function authorize(credentials, scopes) {
  return new Promise((resolve, reject) => {
    googleAuth.fromJSON(credentials, (err, client) => {
      if (err) {
        console.error(err);
        reject(err);
        return;
      }
      client.scopes = scopes;
      client.authorize((err, result) => {
        if (err) {
          console.error(err);
          reject(err);
          return;
        }
        console.log(result, true);
        resolve(client);
      });
    });
  });
}

async function getData(auth, spreadsheetId, range) {
  try {
    return sheets.spreadsheets.values.getAsync({
      auth: auth,
      spreadsheetId: spreadsheetId,
      range: range
    });
  } catch (e) {
    console.error(e);
    throw e;
  }
}

const serviceAccountJson = require('../configs/keys/service_account'); //The service account json key
const spreadsheetId = 'SPREADSHEET_ID'; // Id of the sheet I am trying to access
const apiKey = 'THE_API_KEY'; //Any API key generated on Google's API console
const range = 'A:M';

async function init() {
  let authClient = await authorizeWithServiceAccount(serviceAccountJson, [
    'https://www.googleapis.com/auth/spreadsheets.readonly'
  ]);
  return getData(authClient, spreadsheetId, range); //This doesn't work and throw error
  // return getData(apiKey, spreadsheetId, range); //This does work and return all the data.
}

init()
  .then(result => {
    console.log('Received Data');
    console.log(result.data);
  })
  .catch(e => console.error(e));
所以,如果我使用API密钥而不是服务帐户作为身份验证参数,我将获得预期的正确数据。但是,一旦我使用服务帐户,
result.data
变为
undefined
,然后我得到这个错误

TypeError: callback is not a function
    at JWT.OAuth2Client.postRequest (/Volumes/Projects/Work/node_modules/google-auth-library/lib/auth/oauth2client.js:341:9)
    at postRequestCb (/Volumes/Projects/Work/node_modules/google-auth-library/lib/auth/oauth2client.js:297:23)
    at Request._callback (/Volumes/Projects/Work/node_modules/google-auth-library/lib/transporters.js:113:17)
    at Request.self.callback (/Volumes/Projects/Work/node_modules/request/request.js:186:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (/Volumes/Projects/Work/node_modules/request/request.js:1163:10)
    at emitOne (events.js:116:13)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (/Volumes/Projects/Work/node_modules/request/request.js:1085:12)
TypeError:回调不是函数
在JWT.OAuth2Client.postRequest(/Volumes/Projects/Work/node\u modules/google auth library/lib/auth/OAuth2Client.js:341:9)
在postRequestCb(/Volumes/Projects/Work/node_modules/google auth library/lib/auth/oauth2client.js:297:23)
应请求。\回调(/Volumes/Projects/Work/node\u modules/google auth library/lib/transporters.js:113:17)
at Request.self.callback(/Volumes/Projects/Work/node_modules/Request/Request.js:186:22)
两点钟(events.js:126:13)
at Request.emit(events.js:214:7)
应要求。库版本25.x之前和那个时候服务帐户身份验证都在工作,但当我将其更新到28.x时,它就停止了工作


在28.x node.js客户端中,我是否可以使用服务帐户而不是API密钥?我不能降级,因为我正在使用其他需要最新版本的Google API。

理论:sheets.values.get做的事情非常奇怪,promisify
无法正常工作

可能的解决方案: 手动
promisify
getData

async function getData(auth, spreadsheetId, range) {
  return new Promise((resolve, reject) => {
    sheets.spreadsheets.values.get({
      auth: auth,
      spreadsheetId: spreadsheetId,
      range: range
    }, (error, result) => {
      if (error) {
        return reject(error);
      }
      resolve(result);
    });
  });
}
好的,我又看了一遍,他们在一个地方提到了。我以前是这样使用google auth库的-

const GoogleAuth = require('google-auth-library');
const googleAuth = new GoogleAuth();
这在以前的文档中提到过。我猜在API的文档中,我不记得了。但他们现在使用googleapis包和sheets API支持auth。因此,我所要做的就是切换到使用auth。这就是我现在获取authClient的方式,它正在测试中工作

const { google } = require('googleapis');
const authClient = await google.auth.getClient({
    credentials: credentials,
    scopes: scopes
  });
现在,我得到了最新的正确数据


所以问题是我如何获得authClient。旧的方式似乎与最新的客户端不兼容。

PS:我需要一个橡皮鸭谢谢你的回复。我也有同样的想法并尝试了回调方法,但它仍然给了我同样的错误。问题在于我验证数据的方式。