Google API-endpunkter som använder JavaScript-klientbiblioteket som en Angular 2-tjänst
Jag använder Google API Javascript-biblioteket i min Angular 2-applikation. Jag har skapat en tjänst som injiceras i komponenter. Här är koden:
import { Injectable } from '@angular/core';
const url = 'https://apis.google.com/js/client.js?onload=__onGoogleLoaded';
@Injectable()
export class GoogleAPIService {
public client: any;
public calculatorService: any;
public actionService: any;
loadAPI: Promise<any>
constructor(){
this.loadAPI = new Promise((resolve) => {
window['__onGoogleLoaded'] = (ev) => {
console.log('gapi loaded');
resolve(window['gapi']);
this.client = window['gapi'].client;
this.loadEndPoints('{Endpoint URL}/_ah/api');
}
this.loadScript();
});
}
doSomethingGoogley(){
return this.loadAPI.then((gapi) => {
console.log(gapi);
});
}
loadScript(){
console.log('loading..')
let node = document.createElement('script');
node.src = url;
node.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(node);
}
loadEndPoints(apiRoot) {
// Loads the OAuth and calculatorendpoint APIs asynchronously, and triggers login
// when they have completed.
var apisToLoad;
var callback = function() {
console.log('API Loaded '+apisToLoad);
if (--apisToLoad == 0) {
//this.endpoint1= this.client.endpoint1; //Doesn't Work
//this.endpoint2= this.client.endpoint2;
}
}
apisToLoad = 3; // must match number of calls to gapi.client.load()
this.client.load('oauth2', 'v2', callback);
this.client.load('endpoint1', 'v1', callback, apiRoot);
this.client.load('endpoint2','v1',callback,apiRoot);
}
}
Jag har tre frågor:
- Hur får jag ändpunkterna gapi.client.endpoint1 som en offentlig variabel i tjänsten?
- Hur anropar jag metoderna i API:et? I JavaScript kan du bara anropa gapi.client.endpoint1.method().execute()
- Hur gör jag den här tjänsten till en singleton?
All hjälp uppskattas.
REDIGERA:
Här är den fungerande versionen av tjänsten. Jag använder den som leverantör i min Root-modul. Därför är den tillgänglig som singleton i hela applikationen.
import { Injectable } from '@angular/core';
const url = 'https://apis.google.com/js/client.js?onload=__onGoogleLoaded';
const gapiOnLoaded = '__onGoogleLoaded';
const clientName = 'gapi';
const endpointhost = '[HTTPS URL FOR ENDPOINTS]';
const apiEndPoint = endpointhost + '/_ah/api';
@Injectable()
export class GoogleAPIService {
private gapi: any;
private loadAPI: Promise<any>;
constructor() {
this.loadAPI = new Promise((resolve) => {
window[gapiOnLoaded] = (ev) => {
this.gapi = window[clientName];
// Loads the OAuth and other APIs asynchronously, and triggers login
// when they have completed.
let apisToLoad;
let callback = function() {
if (--apisToLoad === 0) {
resolve(window[clientName]);
}
};
apisToLoad = 3; // must match number of calls to gapi.client.load()
this.gapi.load('client:auth2', callback);
this.gapi.client.load('[ENDPOINT_1_NAME]', 'v1', callback, apiEndPoint);
this.gapi.client.load('[ENDPOINT_2_NAME]', 'v1', callback, apiEndPoint);
};
this.loadScript();
});
}
public GetClient(): any {
return this.loadAPI.then((res) => {
return this.gapi;
});
}
private loadScript() {
let node = document.createElement('script');
node.src = url;
node.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(node);
}
}
Injicera denna tjänst i andra tjänster. Jag skapade en tjänst för varje slutpunkt.
@Injectable()
export class Endpoint1Service {
private gapi: any;
constructor(private googleApiService: GoogleAPIService) {
}
public isLoad() {
return this.googleApiService.GetClient().then((gapi) => {
this.gapi = gapi;
return true;
});
}
public action(data: DataType){
this.gapi.client.endpointname.apimethod(data).execute();
}
}
Svar #1
Tjänster är singletons som standard. Du bör provide den i din AppModule, och då kommer den att vara tillgänglig för alla dina komponenter. Se bara till att inkludera den i dina komponentkonstruktörer.
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HttpModule} from '@angular/http';
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { GoogleService } from './google.service'; // important
@NgModule({
imports: [
BrowserModule,
HttpModule,
routing,
],
declarations: [ AppComponent],
providers: [ GoogleService ], // important
bootstrap: [ AppComponent],
})
export class AppModule {
}
För att göra en slutpunkt tillgänglig utanför din tjänst kan du använda sökordet public framför funktionen som anropar slutpunkten. För att anropa slutpunkten i angular2 kan du använda den inbyggda http-tjänsten från @angular/http. Här är ett exempel på en tjänst (endast med HTTP GET) som kommer att returnera ett Observable för de slutpunkter du anropar.
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs';
@Injectable()
export class GoogleService {
constructor(private http: Http) { }
public endpoint1(): Observable<any> {
return this.http.get("http://endpoint.one.com");
}
public endpoint2(): Observable<any> {
return this.http.get("http://endpoint.two.com");
}
}
Du kan sedan använda tjänsten så här i din komponent.
import { Component, OnInit } from '@angular/core';
import { GoogleService } from './google.service'; // important
@Component({
selector: 'app',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
constructor(private googleService: GoogleService) { }
ngOnInit() {
this.googleService.endpoint1().subscribe(callback1, handleError);
this.googleService.endpoint2().subscribe(callback2, handleError);
}
callback1(data){
// do something with the data from ONE
}
callback2(data){
// do something with the data from TWO
}
handleError(error: any){
console.error(error);
}
}
Jag rekommenderar att läsa lite om att använda Observables i det här inlägget från Angular University.
Svar #2
Jag tror inte att det är särskilt bra praxis att modifiera DOM för att ladda gapi. Det är troligen bättre att använda gapi och gapi.auth TypeScript-definitioner genom att installera dem med NPM.
Jag har lagt upp instruktioner om hur man gör detta i mitt svar på Import gapi.auth2 i Angular 2 TypeScript.
