• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Google Books - API

VPS Starter Arubacloud
0 głosów
790 wizyt
pytanie zadane 6 czerwca 2020 w JavaScript przez Allen Obywatel (1,010 p.)
zamknięte 7 czerwca 2020 przez Allen

Postępuje zgodnie z dokumentacją Googla: https://developers.google.com/books/docs/viewer/developers_guide

Zmienna isbn zawiera poprawny identyfikator, wydaje mi ię że cała reszta również jest w porządku. Pojawia się taki błąd: 

readBtns.forEach(btn => {
  btn.addEventListener('click', (event) => {
    let title = event.path[2].querySelector('.title-ex').textContent;
    let gbUri = 'https://www.googleapis.com/books/v1/volumes?key=MY_KEY&cx=017576662512468239146:omuauf_lfve&q=' + title;
    fetch(gbUri).then(response => response.json()).then(response => {
      //let gbId = response.items[0].id;
      let isbn = response.items[0].volumeInfo.industryIdentifiers[1].identifier;
      google.books.load();
      google.books.setOnLoadCallback(initialize(isbn));
    });
  });
});

function initialize(isbn) {
  const viewerCanvas = document.createElement('div');
  viewerCanvas.id = 'viewerCanvas';
  const viewer = new google.books.DefaultViewer(viewerCanvas);
  viewer.load('ISBN:' + isbn, BookNotLoaded, BookLoaded);
};

 

komentarz zamknięcia: Otrzymałem odpowiedź

1 odpowiedź

+1 głos
odpowiedź 6 czerwca 2020 przez ScriptyChris Mędrzec (190,190 p.)
wybrane 6 czerwca 2020 przez Allen
 
Najlepsza

Postępuje zgodnie z dokumentacją Googla:

google.books.setOnLoadCallback(initialize(isbn));

Chyba nie do końca ;) W dokumentacji do metody setOnLoadCallback przekazywana jest referencja do funkcji initialize a nie wynik jej wywołania:

google.books.setOnLoadCallback(initialize);

Jeśli chcesz przekazać dodatkowy parametr, to możesz przekazać funkcję anonimową:

google.books.setOnLoadCallback(() => initialize(isbn));

P.S. Na przyszłość, nie umieszczaj kluczy do API w kodzie, który wstawiasz w jakiekolwiek publiczne miejsca w sieci - zastąpiłem ten fragment kodu w pytaniu frazą MY_KEY.

komentarz 7 czerwca 2020 przez Allen Obywatel (1,010 p.)
edycja 7 czerwca 2020 przez Allen

console.log(google.books.load()) podpięte tuż pod jsapi.ja pokazuje, że funkcja jest dostępna.

const deleteBtns = document.querySelectorAll('.delete-btn-form');
const readBtns = document.querySelectorAll('.read-btn');
 
deleteBtns.forEach(btn => {
    btn.addEventListener('click', () => {
      btn.submit();
    });
  });
 
readBtns.forEach(btn => {
  btn.addEventListener('click', (event) => {
    google.books.load();
    let title = event.path[2].querySelector('.title-ex').textContent;
    let gbUri = 'https://www.googleapis.com/books/v1/volumes?key=MY_KEY&cx=017576662512468239146:omuauf_lfve&q='+ title;
    fetch(gbUri).then(response => response.json()).then(response => {
      let isbn = response.items[0].volumeInfo.industryIdentifiers[1].identifier;
 
      google.books.setOnLoadCallback(() => initialize(isbn));
    });
  });
});
 
function initialize(isbn) {
    const viewerCanvas = document.createElement('div');
    viewerCanvas.id = 'viewerCanvas';
    const container = document.querySelector('.container');
    container.appendChild(viewerCanvas);
    const viewer = new google.books.DefaultViewer(viewerCanvas);
    viewer.load('ISBN:' + isbn, bookNotLoaded, bookLoaded);
};
 
function bookNotLoaded () {
  console.log('Unable to load book');
}
 
function bookLoaded () {
  console.log('The book has loaded successfully');
  }

Teraz występuje błąd: google.books.setOnLoadCallback is not a function. Gdy linię 18 przeniosę pod 38 zmienna isbn nie jest dostępna.

komentarz 7 czerwca 2020 przez ScriptyChris Mędrzec (190,190 p.)

Hmm..., trudno mi powiedzieć dlaczego tak się dzieje. Wychodzi na to, że w późniejszym etapie działania aplikacji obiekt google.books zmienia swoją strukturę, stąd na etapie obsługi Promisa nie ma dostępu do metod load ani setOnLoadCallback. Żeby znaleźć przyczynę, trzeba by debugować kod.

Może wystarczy funkcję initialize zawołać raz, a potem wołać viewer.load z kolejnymi wartościami isbn operując na referencji viewer i już nie wołać google.books.[load/setOnLoadCallback] więcej niż raz?


Zadam trochę głupie pytanie, ale ile razy wywołujesz setOnLoadCallback? To dzieje się na klik - za którym kliknięciem to nie działa?

komentarz 7 czerwca 2020 przez Allen Obywatel (1,010 p.)
edycja 10 czerwca 2020 przez Allen

Gdy wywołuję funkcję google.books.load() oraz google.books.setOnLoadCallback(initialize), to element viewer jest niezdefiniowany. 

readBtns.forEach(btn => {
  btn.addEventListener('click', (event) => {
    google.books.load();
    console.log('Pierwszy');
    let title = event.path[2].querySelector('.title-ex').textContent;
    let gbUri = 'https://www.googleapis.com/books/v1/volumes?key=MY_KEY&cx=017576662512468239146:omuauf_lfve&q=' + title;
    fetch(gbUri).then(response => response.json()).then(response => {
      let isbn = response.items[0].volumeInfo.industryIdentifiers[1].identifier;
      google.books.setOnLoadCallback(() => initialize(isbn));
    });

    const bookNotLoaded = () => {
    console.log('Unable to load book');
      const fillMsg = document.createElement('div');
      fillMsg.className = 'warningMsg';
      const fillTextMsg = document.createTextNode('Unable to load book');
      fillMsg.appendChild(fillTextMsg);
      const contentModal = document.querySelector('.msg-banner');
      contentModal.appendChild(fillMsg);
    };
    
    const bookLoaded = () => {
    console.log('The book has loaded successfully');
      const warningMsg = document.querySelector('.warningMsg');
      if (warningMsg !== null) {
        warningMsg.parentNode.removeChild(warningMsg);
      }
    };

    const initialize = (isbn) => {
      console.log('Drugie');
      const viewerCanvas = document.createElement('div');
      viewerCanvas.id = 'viewerCanvas';
      const container = document.querySelector('.container');
      container.appendChild(viewerCanvas);
      const viewer = new google.books.DefaultViewer(viewerCanvas);
      viewer.load('ISBN:' + isbn, bookNotLoaded, bookLoaded);
    };
  });
});

W tym kodzie po pierwszym kliknięciu w konsoli pojawia się "Pierwszy", a błąd wyskakuje po drugim i każdym następnym kliknięciu. Gdy po odświeżeniu strony szbko klikam wiele razy w readBtn w konsoli pojawia się kilka razy "Pierwszy" i dopiero błąd.

komentarz 7 czerwca 2020 przez ScriptyChris Mędrzec (190,190 p.)

Przenieś google.books.load() na początek kodu - niech to się wykonuje raz w trakcie działania aplikacji (a nie przy każdym kliku, jak teraz).

Gdy wywołuję funkcję google.books.load() oraz google.books.setOnLoadCallback(initialize), to element viewer jest niezdefiniowany

W którym miejscu viewer jest niezdefiniowany? Tą zmienną tworzysz w funkcji initialize i tylko tu masz teraz do niej dostęp.

Wywołaj funkcję initialize po google.books.load(), ale zmienną viewer trzymaj w zewnętrznym scope - niech w funkcji initialize będzie tylko zainicjowana przez new google.books.DefaultViewer. Dopiero na kliknięcie wołaj funkcję, do której przekażesz isbn i tam dopiero wołaj viewer.load z przekazaniem tego isbn (na takiej zasadzie jak robisz teraz, z tym że inicjuj API tylko raz, na początku).

Coś takiego:

    let viewer = null;
    
    google.books.load();
    google.books.setOnLoadCallback(initialize);

    function initialize () {
      const viewerCanvas = document.createElement('div');
      viewerCanvas.id = 'viewerCanvas';
      const container = document.querySelector('.container');
      container.appendChild(viewerCanvas);
      viewer = new google.books.DefaultViewer(viewerCanvas);
    };

   function loadPage (isbn) {
     viewer.load('ISBN:' + isbn, bookNotLoaded, bookLoaded);
   }

   /* kod obsługujący Promisa zwróconego przez fetch*/
   .then(response => {
      let isbn = response.items[0].volumeInfo.industryIdentifiers[1].identifier;
      loadPage(isbn);
   })
komentarz 7 czerwca 2020 przez Allen Obywatel (1,010 p.)
Wszytko działa. Bardzo dziękuję za pomoc i poświęcony czas, w życiu bym tego sam nie ogarnął.

Podobne pytania

0 głosów
0 odpowiedzi 114 wizyt
pytanie zadane 7 czerwca 2020 w Android, Swift, Symbian przez Paweł123 Nałogowiec (33,500 p.)
0 głosów
1 odpowiedź 239 wizyt
pytanie zadane 19 listopada 2018 w JavaScript przez niezalogowany
0 głosów
2 odpowiedzi 1,045 wizyt
pytanie zadane 26 maja 2020 w JavaScript przez frederrer Użytkownik (740 p.)

93,025 zapytań

141,990 odpowiedzi

321,293 komentarzy

62,374 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...