2016-06-29 7 views
3

Ich habe versucht, einige Klassen oder Funktion von Google gapi.auth2 in Typoskript zu importieren. Aber unterhalb von Code funktioniert nie sogar ich habe die gapi.auth2 Typen im typings Verzeichnis korrekt hinzugefügt.Import gapi.auth2 in angular 2 Typoskript

import { GoogleAuth } from 'gapi.auth2';

Ich habe immer Fehler:

Error TS2307: Cannot find module 'gapi.auth2'

Soll ich eine gewisse relative Verzeichnissuche verwenden, wie zum Beispiel‘../../typings/gapi.auth2' ?

Oder ist die Art, wie ich den Gapi benutze, völlig falsch?

Danke!

+0

Werfen Sie einen Blick auf die Importanleitung https://www.typescriptlang.org/docs/handbook/module-resolution.html – AngJobs

Antwort

0

Der Compiler versucht, eine Umgebungsmoduldeklaration zu finden. So sollten Sie installieren:

https://github.com/retyped/gapi.auth2-tsd-ambient

+0

Soll ich so verwenden? '' 'Importiere {GoogleAuth} von 'retyped-gapi.auth2-tsd-ambient';' ''. Ich habe immer noch einen Fehler '' 'Fehler TS2307: Kann das Modul 'retyped-gapi.auth2-tsd-ambient'''' nicht finden, nachdem ich gesehen habe, dass das Paket unter node_modules installiert ist. Vielen Dank. –

16

gapi und gapi.auth mit Angular2 zu verwenden, um die Art Skript-Definitionen NPM installieren.

npm install --save @types/gapi 
npm install --save @types/gapi.auth2 

Dies wird zwei Pakete, @types/gapi und @types/gapi.auth2 zum node_modules Ordner installieren und die Konfiguration in package.json speichern.

Überprüfen Sie Ihre node_modules Ordner, um zu überprüfen, ob sie korrekt installiert sind. Wenn Ihr Angular2 App Haupt-App genannt, sollten Sie sehen:

main-app/ 
    node_modules/ 
    @types/ 
     gapi/ 
     gapi.auth2/ 

bearbeiten tsconfig.json neue gapi und gapi.auth2 Typen umfassen (unten ist nur ein Auszug):

{ 
    "compileOnSave": false, 
    "compilerOptions": { 
    "types": ["gapi", "gapi.auth2"] 
    } 
} 

An diesem Punkt ist hoch empfehlen einen Kaffee greifen und Lese Typescript Module Resolution, können Sie direkt zu überspringen Wie Node.js Module löst:

[...] resolution for a non-relative module name is performed differently. Node will look for your modules in special folders named node_modules . A node_modules folder can be on the same level as the current file, or higher up in the directory chain. Node will walk up the directory chain, looking through each node_modules until it finds the module you tried to load.

Aus diesem Grund sollten Sie in Ihrem Angular2 Service oder Ihrer Komponente (oder wo immer Sie gapi oder gapi.auth2 verwenden) keinen Verweis auf die Typdefinitionen hinzufügen müssen.

Wenn Sie jedoch auf die gapi oder gapi.auth2 Typoskript Definitionen eine Referenz zu tun hinzuzufügen, muss er die .ts Datei verweisen installiert mit npm install (beachten Sie, Sie /// halten müssen oherwise Sie einen Fehler finden):

/// <reference path="../../node_modules/@types/gapi/index.d.ts" /> 

Der Pfad ist relativ, so dass Sie davon abweichen können, je nachdem, wo sich Ihre .ts-Datei in Bezug auf die Stelle befindet, an der Sie die TypeScript-Definitionen installiert haben.

Ob Sie einen expliziten Verweis hinzugefügt oder den Typskript-Node-Modul-Auflösungsmechanismus verwendet haben, müssen Sie Ihre Variablen immer noch in Ihrer .ts-Datei deklarieren, damit Angular2 die Window-Gapi-Variable zur Kompilierzeit kennt.Fügen Sie declare var gapi: any; zu Ihrer .ts Datei hinzu, aber tun Sie nicht platzieren Sie es innerhalb einer Klassendefinition. Ich habe meine knapp unter irgendwelchen Importen:

// You may not have this explicit reference. 
/// <reference path="../../node_modules/@types/gapi/index.d.ts" /> 
import { NgZone, Injectable, Optional } from '@angular/core'; 
declare var gapi: any; 

bei den Definitionen der Suche selbst (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/gapi/index.d.ts) werden nur Funktionen exportiert. Umgekehrt sind die Schnittstellen Implementierungsdetails, so dass sie nicht exportiert werden und für Code außerhalb des Namensraums nicht sichtbar sind.

Arbeiten mit anderen JavaScript-Bibliotheken in TypeScript documentation ist lesenswert, um zu verstehen, was wir mit all dieser Arbeit bekommen.

Als nächstes laden Sie die gapi Client mit Ihrer eigenen Funktion (möglich in einem Winkel Service):

loadClient(): Promise<any> { 
    return new Promise((resolve, reject) => { 
     this.zone.run(() => { 
       gapi.load('client', { 
        callback: resolve, 
        onerror: reject, 
        timeout: 1000, // 5 seconds. 
        ontimeout: reject 
       }); 
     }); 
    }); 
} 

Diese Funktion ist nicht trivial, und das aus gutem Grund ...

Zum einen Vermerk Wir rufen gapi.load mit einem Konfigurationsobjekt und nicht nur einen Rückruf. Die GAPI reference Zustände können entweder verwendet werden:

  • Eine Rückruffunktion, die aufgerufen wird, wenn die Bibliotheken Laden beendet haben.
  • Ein Objekt, das die verschiedenen Konfigurationsparameter für diese Methode einkapselt. Nur ein Rückruf ist erforderlich.

eine Konfigurationsoption verwenden können wir das Versprechen ablehnen, wenn die Bibliothek mal-out Laden, oder einfach nur Fehler. Nach meiner Erfahrung schlägt das Laden der Bibliothek häufiger fehl als das Initialisieren - weshalb das Konfigurationsobjekt besser ist als nur ein Callback.

Zweitens, wir wickeln gapi.load in

this.zone.run(() => { 
    // gapi.load 
}); 

NgZone.run is documented und Staaten

Running functions via zone.run allows you to reenter Angular zone from a task that was executed outside of the Angular zone [...]

Das ist genau das, was wir wollen, da der Aufruf an gapi.load die Winkelzone verlässt. Wenn man dies auslässt, kann das zu sehr funky Ergebnissen führen, die schwer zu debuggen sind.

Drittens gibt loadClient() ein Versprechen zurück, das aufgelöst wird - dem Anrufer zu ermöglichen, zu wählen, wie sie mit gapi.load umgehen. Zum Beispiel, wenn unsere loadClient Verfahren zu einem Winkel Dienst gehören, apiLoaderServce kann eine Komponente ngOnInit verwendet gapi laden:

ngOnInit(): void { 
    this.apiLoaderService.loadClient().then(
     result => this.apiLoaded = true, 
     err => this.apiLoaded = false 
    ); 
} 

Sobald gapi.load aufgerufen wurde, gapi.client bereit sein wird, und Sie sollten es verwenden, um den JavaScript-Client initialisiert mit Ihnen API-Schlüssel, OAuth-Client-ID, Umfang und API-Erkennungs-Dokument (e):

initClient(): Promise<any> { 
    var API_KEY = // Your API key. 
    var DISCOVERY_DOC = // Your discovery doc URL. 
    var initObj = { 
     'apiKey': API_KEY, 
     'discoveryDocs': [DISCOVERY_DOC], 
    }; 

    return new Promise((resolve, reject) => { 
     this.zone.run(() => { 
      gapi.client.init(initObj).then(resolve, reject); 
     }); 
    }); 
} 

Hinweis unser Freund NgZone.run wird wieder verwendet, um die Winkelzone, um sicherzustellen, erneut eingegeben.In der Praxis füge ich loadClient() und initClient() zu einem Angular Service hinzu. In einer High-Level-Winkelkomponente (in der Regel nur unter der App-Komponente) I geladen und initialisiert in ngOnInit:

ngOnInit(): void { 
    this.apiLoaderService.loadClient().then(
     result => { 
      this.apiLoaded = true; 
      return this.apiLoaderService.initClient() 
     }, 
     err => { 
      this.apiFailed = true; 
     } 
    ).then(result => { 
     this.apiReady = true; 
    }, err => { 
     this.apiFailed = true; 
    }); 
} 

Schließlich müssen Sie die gapi Skript-Datei auf Ihre Datei hinzuzufügen.

<html> 
    <head> 
    <script src="https://apis.google.com/js/api.js"></script> 

müssen Sie nicht die asyncoderdefer Attribute verwenden, da entweder Angular 2 Welt verursachen wird, bevor gapi geladen ist einzugeben.

<!-- This will not work. --> 
<html> 
    <head> 
    <script async defer src="https://apis.google.com/js/api.js"></script> 

ich vorher hatte vorgeschlagen Seitenladegeschwindigkeit schnell zu halten durch eine lokale, minimierte Kopie des gapi library im /main-app/src/assests Ordner Laden und Importieren:

<html> 
     <head> 
     <script src="assets/api.js"></script> 

jedoch ich stark empfehlen nicht tun dies. Google aktualisiert möglicherweise https://apis.google.com/js/api.js und Ihr Client wird beschädigt. Ich bin zweimal davon überrascht worden. Am Ende war es besser, einfach von zu importieren und es als Blockierruf zu behalten.

+0

Nachdem Sie '@ types/gapi' und' @ types/gapi.auth2' installiert haben, wie verwenden Sie diese Typen in Ihrem Code? Beispielsweise haben Sie das Versprechen als "Versprechen " definiert. Wie könnte ich etwas wie "Promise " machen? – zanderle

+0

@zanderle verwenden Sie es als 'gapi.auth2.GoogleAuth', auch Wenn Sie, wie ich, ein neues Projekt mit angular-cli gestartet haben, sollte webpack weinen, dass Sie den gapi-Namespace nicht finden, fügen Sie die Typen zu tsconfig.app hinzu. Json. da das eckige Team entschieden hat, dass sie keine automatischen '../ node_modules/@ types' -Inklusionen benötigen, was das Webpack beim Ausführen von Bündeln durcheinander bringt. – GradientByte