Асинхронная аутентификация с использованием API Google

У меня есть следующий код:

async function initApi() {
  const googleKey = await readJSON(appRoot + '/secrets/google-auth.json');

  const jwt = new google.auth.JWT(
    googleKey.client_email, null, googleKey.private_key, scopes);

  return jwt.authorize();
}

const calendar = {
  events: events,

  api: google.calendar({
    version: 'v3',
    auth: this.jwt
  }),

  list: async function() {
    await this.api.calendarList.list();
  },
};

module.exports = async () => Object.assign(calendar, { jwt: await initApi() });

Я постоянно получаю сообщение «Требуется ошибка входа». Тем не менее jwt прекрасно разрешает токен доступа, когда я регистрирую результат:

const Calendar = require('./above-code.js');

Calendar().then(c => console.info(c.jwt));
// { access_token: ... }

Calendar().then(c => console.info(c.list());
// Error: login required

Я не могу понять, почему. Это сводит меня с ума. Я хочу выбросить свой ноутбук в окно.

Что я делаю неправильно? Это лучший шаблон с использованием async и await с module.exports? Есть ли лучший способ просто вернуть объект, чтобы я мог вызвать Calendar.list() и получить результат без необходимости прыгать через обручи, которые я сейчас делаю, чтобы просто получить API и вызвать методы напрямую? Например.:

const Calendar = require('./above-code.js');
await Calendar.list();
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
613
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы добавляете jwt в объект, а не как отдельную переменную, так должно быть:

  google.calendar({
    version: 'v3',
    auth: this.jwt //here
}),

Object.assign(calendar, { jwt: 'value' }); эквивалентен calendar.jwt = 'value'. И вы ссылаетесь, как будто это было сделано таким образом:

let jwt  = 'value';
  google.calendar({
    version: 'v3',
    auth: jwt //here
}),

Извините, я не совсем понимаю. Это точный код, который у меня есть в вопросе. Можете ли вы уточнить немного больше?

Nick Bull 11.02.2019 15:07

Извините, бато, похоже, это не было проблемой для меня. Я отвечу через секунду!

Nick Bull 11.02.2019 17:32
Ответ принят как подходящий

Сделал перерыв, прежде чем вернуться к этому - лучшее решение для меня, кажется, становится менее разочарованным, прежде чем я продолжу разочаровывающую проблему.

Во-первых, я переместил свойство api в функцию initApi и вернул его туда — похоже, это решило мой вопрос:

async function initApi() {
  const googleKey = await readJSON(appRoot + '/secrets/google-auth.json');

  const jwt = new google.auth.JWT(
    googleKey.client_email, null, googleKey.private_key, scopes);

  jwt.authorize();

  return google.calendar({
    version: 'v3',
    auth: jwt
  });
}

const calendar = {
  events: events,

  list: async function() {
    await this.api.calendarList.list();
  },
};

module.exports = async () => Object.assign(calendar, { api: await initApi() });

Однако второе предостережение заключалось в том, что теперь он продолжал жаловаться на то, что client.request не найден — оказывается, у Google есть два набора инструментов аутентификации.

После перехода на google-auth-library (вместо использования встроенного googleapis в auth.JWT) я получил ответ от сервера без жалоб на client.request:

const { google } = require('googleapis');
const { JWT } = require('google-auth-library');

...

async function initApi() {
  const googleKey = await readJSON(appRoot + '/secrets/google-auth.json');

  const jwt = new JWT(
    googleKey.client_email, null, googleKey.private_key, scopes);

  return await google.calendar({
    version: 'v3',
    auth: jwt
  });
}

Теперь это работает! Надеюсь, это поможет любому, у кого есть эта проблема.

РЕДАКТИРОВАТЬ: Кроме того, см. пример Google здесь для загрузки аутентификации из загружаемого файла JSON с панели управления Google API.

Ответ несколько сложен из-за того, как автор строит объект модуля.

Вот упрощенная версия, которая использует промисы и не требует google-auth-library.

const { google } = require("googleapis");

function auth() {
  const gAccount = //

  const jwt = new google.auth.JWT(gAccount.client_email, null, gAccount.private_key, gAccount.scope);
  return jwt.authorize().then(() => google.calendar({ version: "v3", auth: jwt }));
}

function listCalendars() {
  return auth().then(calendar => {
    return calendar
      .calendarList.list({ showHidden: true })
      .then(res => res.data.items);
  });
}

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