【问题标题】:Google API Endpoints using Javascript client library as an Angular 2 Service使用 Javascript 客户端库作为 Angular 2 服务的 Google API 端点
【发布时间】:2016-09-22 07:58:17
【问题描述】:

我在我的 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 作为服务中的公共变量?
  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();
    }
}

【问题讨论】:

  • 第一个问题是什么意思?看起来您已经有一个 const url = ... 来跟踪 google api url。你想发生什么?
  • 我有多个端点.. 所以我想将它们分配给单独的公共变量.. 这样我就可以在组件中将它们用作 myservice.endpoint1service
  • @Akanksha 这对我帮助很大!你有这方面的更新吗?也许您可以发布最新版本的从 Angular 2 连接到 Cloud Endpoints 的方法(包括您在对已接受答案的回复中提到的包装器)?
  • @jonasjuss 我已经在上面发布了解决方案。希望对你有帮助
  • @jonasjuss 您必须提供回调。建议您不要使用 gapi,因为它不会返回 observable。您应该使用 Angular 2 的 HttpModule 从谷歌端点请求数据。

标签: javascript angular typescript google-api-client angular2-services


【解决方案1】:

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

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),它将为您调用的端点返回一个 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 的内容。

【讨论】:

  • 谢谢,我最终为每个端点创建了包装器。您的样本为我指明了正确的方向
【解决方案2】:

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

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

【讨论】:

  • 我同意。我最终创建了自己的服务,该服务可以访问 google auth url 并获取访问令牌。
猜你喜欢
  • 2017-02-11
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 2012-12-15
相关资源
最近更新 更多