Google API 端点使用 Javascript 客户端库作为 Angular 2 服务

Google API Endpoints using Javascript client library as an Angular 2 Service

我在 Angular 2 应用程序中使用 Google API Javascript 库。我创建了一个注入组件的服务。这是代码:

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);

  }
}

我有三个问题:

  1. 如何获取端点 gapi.client.endpoint1 作为服务中的 public 变量?
  2. 如何调用api中的方法?在 javascript 中,您可以调用 gapi.client.endpoint1.method().execute()
  3. 如何使该服务成为单例?

感谢任何帮助。

编辑:

这是该服务的工作版本。我将它用作我的根模块中的提供者。因此,它在整个应用程序中作为单例可用。

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);
  }
}

在其他服务中注入此服务。我为每个端点创建了一个服务。

@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();
    }
}

服务默认是单例的。您应该 provide 在您的 AppModule 中使用它,然后它将对您的所有组件可用。只要确保将它包含在您的组件构造函数中即可。

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 {
}

要使端点在您的服务之外可用,您可以在调用端点的函数前面使用 public 关键字。要在 angular2 中调用端点,您可以使用来自 @angular/http 的内置 http 服务。这是一个示例服务(仅使用 HTTP GET),它将 return 您调用的端点的 Observable。

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");
    }

}

然后您可以在您的组件中使用这样的服务。

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);
    }

}

我建议阅读 Angular 大学的 this post 中关于使用 Observables 的内容。

我不认为修改 DOM 来加载 gapi 是特别好的做法。通过使用 NPM 安装 gapigapi.auth TypeScript 定义可能会更好。

我在对 Import gapi.auth2 in angular 2 typescript 的回答中发布了有关如何执行此操作的说明。