(Node.js) Значения API таблиц v4 # Функция batchGet игнорирует диапазоны

Я обнаружил странное поведение в Google Sheets API (это проблема?): Журнал функций Firebase не показывает ошибок, но функция values#batchGet игнорирует диапазоны. Он возвращает весь dataRange листа в первом диапазоне.

batchGet "Попробуйте этот API"

Я отредактировал свой код на основе кода Github: проблема с параметром пакетов API Таблиц и получения диапазонов

sheets.spreadsheets.values.batchGet({
  // your options
}, function (err, data, response) {
  console.info(response.req.res.request.url);
});

Часть кода Node.js:

const sheets = google.sheets({ version: 'v4', access_token });  
// set auth as a global default:
google.options({ auth: jwt }); 

const request = {
  auth: jwt,
  spreadsheetId: 'xxxxx', //<---------- "Project Checklist" and "Control" sheets
  ranges: [
    "'Project Checklist'!B:K",
    "Control!A:F"
  ],
  majorDimension: "ROWS",
  dateTimeRenderOption: "FORMATTED_STRING",
  valueRenderOption: "FORMATTED_VALUE"
}

Это заключено в обещание ...

sheets.spreadsheets.values.batchGet(request, (err, data, response) => {
  console.info("inside: sheets.spreadsheets.values.batchGet() --------"); 
  if (err) {
    console.info('The Sheets API returned an error: ' + err);
    //The API returned an error: Error: API key not valid. Please pass a valid API key.
    reject(err);
  };      
  try {
    console.info("response:-------------------------------");
    console.info(JSON.stringify(response));

    console.info("data.valueRanges:-------------------------------");
    console.info(data.valueRanges); 
    resolve(JSON.stringify(data.valueRanges));
  } catch (err) {
    console.info("Error processing Sheets API response: " + err);
    reject(err);
  }    
})

(Node.js) Значения API таблиц v4 # Функция batchGet игнорирует диапазоны

Журнал Firebase:

Function execution took 3822 ms, finished with status code: 200
undefined
data.valueRanges:-------------------------------
undefined
response:-------------------------------
getJwt() --------------- OK

index.js

'use strict'
const functions = require('firebase-functions');
const { google } = require('googleapis');
var serviceAccount = require("./credentials/admin-service-account-key.json");

function getJwt() {
  // Define the required scopes.
  var scopes = [
    'https://www.googleapis.com/auth/spreadsheets'
  ];
  return new google.auth.JWT(
    serviceAccount.client_email,
    null,
    serviceAccount.private_key,
    scopes
  );
}

function getSpreadsheetData(jwt) {

  return new Promise((resolve, reject) => {
    jwt.authorize((error, access_token) => {
      if (error) {
        console.info('Error in jwt.authorize: ' + error);
        reject(error);
      } else {
        // access_token ready to use to fetch data and return to client
        const sheets = google.sheets({ version: 'v4', access_token });

        // set auth as a global default:
        google.options({ auth: jwt }); //<---------------------- 

        const request = {
          auth: jwt,
          spreadsheetId: 'xxxxxxxxxxxxxxxxxxxx', //<---------- Project Checklist / Control
          range: 'Control!A:F', //
        }

        sheets.spreadsheets.values.get(request, (err, response) => {
      console.info("inside: sheets.spreadsheets.values.get() -------------------------------");

          if (err) {
            console.info('The Sheets API returned an error: ' + err);
            //The API returned an error: Error: API key not valid. Please pass a valid API key.
            reject(err);
          };

          try {
            var numRows = response.data.values ? response.data.values.length : 0;
            console.info('%d rows retrieved.', numRows);

            console.info("response.data:-------------------------------");
            console.info(response.data.values);

            resolve(response.data.values);

          } catch (err) {
            console.info("Error processing Sheets API response: " + err);
            reject(err);
          }

        })

      }
    })
  })

}

function getSheetBatchData(jwt) {
  return new Promise((resolve, reject) => {
    jwt.authorize((error, access_token) => {
      if (error) {
        console.info('Error in jwt.authorize: ' + error);
        reject(error);
      } else {
        // access_token ready to use to fetch data and return to client
        const sheets = google.sheets({ version: 'v4', access_token });
        // set auth as a global default:
        google.options({ auth: jwt }); //<---------------------- 

        const request = {
          auth: jwt,
          spreadsheetId: 'xxxxxxxxxxxxxxxxxxxxxxxxxx', //<---------- Project Checklist / Control
          ranges: [
            "Project Checklist!B:K",
            "Control!A:F"
          ],
          majorDimension: "ROWS",
          dateTimeRenderOption: "FORMATTED_STRING",
          valueRenderOption: "FORMATTED_VALUE"
        }

        /*
          sheets.spreadsheets.values.batchGet({
            // your options
          }, function (err, data, response) {
            console.info(response.req.res.request.url);
          });
        */

            //https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/batchGet
        sheets.spreadsheets.values.batchGet(request, (err, data, response) => {

          if (err) {
            console.info('The Sheets API returned an error: ' + err);
            //The API returned an error: Error: API key not valid. Please pass a valid API key.
            reject(err);
          };

          try {

            /*
             * Returns: Array: data.valueRanges = 
             * [
             *   "range": "....",
             *   "values": []
             * ]
             */

            console.info("response:-------------------------------");
            console.info(JSON.stringify(response));

            console.info("data.valueRanges:-------------------------------");
            console.info(data.valueRanges);
            resolve(JSON.stringify(data.valueRanges));

          } catch (err) {
            console.info("Error processing Sheets API response: " + err);
            reject(err);
          }

        });

      }
    })
  })
}



/* Working */
exports.getControlSheetData = functions.https.onCall((data, context) => {
  console.info("getData()---------------------------");
  if (!context.auth) {
    throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + 'while authenticated.');
  } else {
    console.info("context.auth ------------ OK");
    const uid = context.auth.uid;
    console.info(uid);

    var jwt = getJwt();
    console.info("getJwt() --------------- OK");

    return getSpreadsheetData(jwt); //<------------ Requested Spreadsheet's Data

  }
})

    /* Error */
    exports.getBatchData = functions.https.onCall((data, context) => {
  console.info("getBatchData()---------------------------");
      if (!context.auth) {
        throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + 'while authenticated.');
      } else {
        console.info("context.auth ------------ OK");
        const uid = context.auth.uid;
        console.info(uid);

        var jwt = getJwt();
        console.info("getJwt() --------------- OK");

        return getSheetBatchData(jwt); //<------------ Requested Spreadsheet's Data

      }
    })

Новый тест: index.js

'use strict'
const functions = require('firebase-functions');
const { google } = require('googleapis');
var serviceAccount = require("./credentials/admin-service-account-key.json");

function getJwt() {
  // Define the required scopes.
  var scopes = [
    'https://www.googleapis.com/auth/spreadsheets'
  ];
  return new google.auth.JWT(
    serviceAccount.client_email,
    null,
    serviceAccount.private_key,
    scopes
  );
}

function getDataTest2(jwt) {
  jwt.authorize().then(access_token => {
    // access_token ready to use to fetch data and return to client
    const sheets = google.sheets({ version: 'v4', access_token });  
    // set auth as a global default:
    google.options({ auth: jwt }); //<----------------------  

    const request = {
      auth: jwt,
      spreadsheetId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
      ranges: [
        "Project Checklist!B:K",
        "Control!A:F"
      ],
      majorDimension: "ROWS",
      dateTimeRenderOption: "FORMATTED_STRING",
      valueRenderOption: "FORMATTED_VALUE"
    }

    function callback(data,resp) {
      try {
      console.info("inside callback-----------");

      console.info("returned data:--------------")
      console.info(data);

      console.info("returned resp:--------------")
      console.info(resp);

      console.info("expected data.valueRanges------------------------")
      console.info(data.valueRanges);  //<--------- expected data.valueRanges
      return JSON.stringify(data.valueRanges);

      } catch(err) {
        console.info('The Sheets API returned an error: ' + err);
        //The API returned an error: Error: API key not valid. Please pass a valid API key.
        return(err);
      }
    }

    sheets.spreadsheets.values.batchGet(request, callback);

  }).catch(error => {
    console.info('Error in jwt.authorize: ' + error);
    reject(error);
  })
}


exports.getBatchData = functions.https.onCall((data, context) => {
  console.info("getBatchData()---------------------------");
  if (!context.auth) {
    throw new functions.https.HttpsError('failed-precondition', 'The     function must be called ' + 'while authenticated.');
  } else {
    console.info("context.auth ------------ OK");
    const uid = context.auth.uid;
    console.info(uid);

    var jwt = getJwt();
    console.info("getJwt() --------------- OK");

    //return getSheetBatchData(jwt); //<------------ Requested Spreadsheet's Data
    return getDataTest2(jwt)

  }
})

(Node.js) Значения API таблиц v4 # Функция batchGet игнорирует диапазоны

Журнал Firebase:

getJwt()--------------- OK
Function execution took 965 ms, finished with status code: 200

inside callback-----------
returned data: --------------
null
returned resp: --------------

{
  status: 200, statusText: 'OK', headers: { 'content-type': 'application/json; charset=UTF-8', vary: 'Origin, X-Origin, Referer', date: 'Tue, 18 Sep 2018 02:28:15 GMT', server: 'ESF', 'cache-control': 'private', 'x-xss-protection': '1; mode=block', 'x-frame-options': 'SAMEORIGIN', 'alt-svc': 'quic = ":443"; ma=2592000; v = "44,43,39,35"', connection: 'close', 'transfer-encoding': 'chunked' }, config: { adapter: [Function: httpAdapter], transformRequest: { '0': [Function: transformRequest] }, transformResponse: { '0': [Function: transformResponse] }, timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: 2147483648, validateStatus: [Function], headers: { Accept: 'application/json, text/plain, */*', 'Accept-Encoding': 'gzip', 'User-Agent': 'google-api-nodejs-client/0.2.1 (gzip)', Authorization: 'Bearer ya29.c.ElocBg_A_xxxxxxxxxxxxxxxxxxxx' }, method: 'get', access_token: { access_token: 'ya29.c.ElocBg_A_xxxxxxxxxxxxxxxxxx', token_type: 'Bearer', expiry_date: 1537241286000, id_token: undefined, refresh_token: 'jwt-placeholder' }, url: 'https://sheets.googleapis.com/v4/spreadsheets/xxxxxxxxxxxxxxxxxxxxxxxxxxx/values:batchGet', paramsSerializer: [Function], data: undefined, params: { ranges: [Object], majorDimension: 'ROWS', dateTimeRenderOption: 'FORMATTED_STRING', valueRenderOption: 'FORMATTED_VALUE' } }, request: ClientRequest {
domain: null, _events: { socket: [Function], abort: [Function], aborted: [Function], error: [Function], timeout: [Function], prefinish: [Function: requestOnPrefinish] }, _eventsCount: 6, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, upgrading: false, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: false, sendDate: false, _removedHeader: { }, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: null, npnProtocol: false, alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 8, connecting: false, _hadError: false, _handle: null, _parent: null, _host: 'sheets.googleapis.com', _readableState: [Object], readable: false, domain: null, _maxListeners: undefined, _writableState: [Object], writable: false, allowHalfOpen: false, destroyed: true, _bytesDispatched: 563, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: null, _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], read: [Function], _consuming: true, write: [Function: writeAfterFIN], _idleNext: null, _idlePrev: null, _idleTimeout: -1 }, connection: TLSSocket {
  _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: null, npnProtocol: false, alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 8, connecting: false, _hadError: false, _handle: null, _parent: null, _host: 'sheets.googleapis.com', _readableState: [Object], readable: false, domain: null, _maxListeners: undefined, _writableState: [Object], writable: false, allowHalfOpen: false, destroyed: true, _bytesDispatched: 563, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: null, _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], read: [Function], _consuming: true, write: [Function: writeAfte
...
expected data.valueRanges------------------------
The Sheets API returned an error: TypeError: Cannot read property     'valueRanges' of null

Можете ли вы отладить эту функцию? Установите точку останова в обратном вызове и определите фактическую структуру аргументов функции обратного вызова. Во-первых, ваш код предполагает, что data - это объект со свойством valueRange - это точно? Вы не показываете, что это так. Мне также очень странно, что ваша переменная response в обратном вызове - это undefined. Это говорит мне о том, что вы неправильно выполняете функцию.

tehhowch 17.09.2018 19:01

Пока решения нет. sheet. spreadsheets.values.get () отлично работает. sheet. spreadsheets.values.batchGet () - в моем случае не работает.

Alex Pilugin 18.09.2018 13:59

И пробовали ли вы предложение в проблеме GitHub, на которую вы ссылаетесь? В частности, github.com/googleapis/google-api-nodejs-client/issues/…?

tehhowch 18.09.2018 15:11

Как насчет изменения в вашем первоначальном сценарии до sheets.spreadsheets.values.batchGet(request, (err, data, response) => {console.info(data.data.valueRanges)})? В моей среде это отлично работает с [email protected]. Но если это не сработало в вашей среде, мне очень жаль.

Tanaike 20.09.2018 00:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
726
0

Другие вопросы по теме