2016-06-29 3 views
3

Google gapi.auth2에서 타이프 스크립트로 일부 클래스 또는 기능을 가져 오려고했습니다. 하지만 코드 아래에 입력 한 디렉토리에 gapi.auth2 유형을 올바르게 추가해도 작동하지 않습니다. 이러한 '../../typings/gapi.auth2'로,2 각형 입력에서 gapi.auth2 가져 오기

Error TS2307: Cannot find module 'gapi.auth2'

내가 어떤 상대 디렉토리 검색을 사용한다

import { GoogleAuth } from 'gapi.auth2';

나는 항상 오류가 발생했습니다?

어쩌면 나는 gapi를 사용하고있는 방식이 완전히 잘못 되었습니까?

감사합니다.

+0

수입 지침을 확인하십시오. https://www.typescriptlang.org/docs/handbook/module-resolution.html – AngJobs

답변

0

컴파일러는 주변 모듈 선언을 찾습니다. 그래서 당신은 설치해야합니다, Angular2와 gapigapi.auth를 사용 NPM을 사용하여 유형 스크립트 정의를 설치하려면

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

+0

다음과 같이 사용합니까? '''{GoogleAuth}를 'retyped-gapi.auth2-tsd-ambient'에서 가져 오면,'''. 오류가 발생했습니다.'''오류 TS2307 : 패키지가 node_modules 아래에 설치된 것을 본 후 'retyped-gapi.auth2-tsd-ambient'''' 모듈을 찾을 수 없습니다. 감사. –

16

.

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

이 두 패키지의 node_modules 폴더에 @types/gapi@types/gapi.auth2를 설치하고 package.json의 구성을 저장합니다.

node_modules 폴더가 올바르게 설치되어 있는지 확인하십시오. 당신의 Angular2 응용 프로그램이 주 응용 프로그램을 호출하면, 당신은 볼 수 :

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

편집 tsconfig.json 새로운 gapigapi.auth2 유형을 포함 (아래 단지 발췌) :

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

을이 시점에서 나는 매우

[...] 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.

0,123,516 : Node.js를 모듈를 해결하는 방법 커피를 잡아 Typescript Module Resolution을 읽어 보시기 바랍니다, 당신은 로 바로 건너 뛸 수 있습니다

이러한 이유 때문에 Angular2 Service 또는 Component (또는 gapi 또는 gapi.auth2을 사용하는 모든 곳)에서 유형 정의에 대한 참조를 추가 할 필요가 없습니다. 당신이 gapi 또는 gapi.auth2 타이프 라이터 정의에 대한 참조를 추가 할 경우

그러나, 그것은 (당신이 오류가 발생합니다 oherwise 당신이 ///을 유지해야하며, 주) npm install를 사용하여 설치 한 .ts 파일을 참조해야합니다

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

경로가 상대 경로이므로 .ts 파일이 TypeScript 정의를 설치 한 위치와 관련하여 위치가 다를 수 있습니다.

명시 적 참조를 사용하든 TypeScript의 노드 모듈 확인 메커니즘을 사용하든간에 Angular2는 컴파일시에 window gapi 변수를 알 수 있도록 .ts 파일에서 변수를 선언해야합니다..ts 파일에 declare var gapi: any;을 추가하고 이 아닌 경우을 클래스 정의 내에 배치하십시오. 난 그냥 어떤 수입 아래 광산을 넣어 :

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

이 정의 자체 (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/gapi/index.d.ts)을 보면, 단지 기능을 수출하고 있습니다. 반대로 인터페이스는 구현 세부 사항이므로 반출되지 않고 네임 스페이스 외부의 코드에서 볼 수 없습니다.

다른 JavaScript 라이브러리와의 작업 (TypeScript documentation)은이 모든 작업에서 우리가 얻고있는 것을 이해하는 데 가치가 있습니다.

다음으로, 자신의 기능 (각도 서비스에서 가능)을 gapi 클라이언트를로드

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

이 기능은 아닌 사소한, 그리고 좋은 이유 ... 첫째

, 참고 콜백이 아닌 구성 객체를 사용하여 gapi.load이라고 부릅니다. GAPI reference 상태 중 하나를 사용할 수 있습니다

  • 라이브러리가 로드를 완료 한 때 호출되는 콜백 함수.
  • 이 메서드에 대해 다양한 구성 매개 변수 을 캡슐화하는 개체입니다. 콜백 만 필요합니다.

는 구성 옵션을 사용하면 라이브러리 번 아웃로드하거나 오류 때 약속을 거부 할 수있게 해준다. 필자의 경험에 따르면 라이브러리를로드하는 것은 초기화하는 것보다 자주 실패합니다. 따라서 구성 객체가 단순한 콜백보다 낫습니다.

둘째, 우리는

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

NgZone.run is documentedgapi.load을 포장하고 있고이 정확히 gapi.load에 대한 호출이 각도 영역을 잎 때문에 우리가 원하는 것입니다

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

말한다. 이를 생략하면 디버깅하기가 힘든 매우 펑키 한 결과가 남을 수 있습니다.

세 번째로 loadClient()은 해결 된 약속을 반환합니다. 발신자가 gapi.load을 처리하는 방법을 선택할 수 있습니다.

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

호출 된 gapi.load되면, gapi.client이 준비가 될 것입니다 그리고 당신은 자바 스크립트 클라이언트를 초기화하는 데 사용한다 : 우리의 loadClient 방법은 각도 서비스, apiLoaderServce에 속한 예를 들어, ngOnInit를 사용할 수있는 구성 요소는 gapi를로드 당신 API 키, OAuth 클라이언트 ID, 범위 및 API 검색 문서 (들) :

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

공지 사항 우리의 친구 NgZone.run는 각 영역을 다시 입력하기 위해 다시 한 번 사용됩니다.

실제로 각도 서비스에 loadClient()initClient()을 추가합니다. (대개 응용 프로그램 구성 요소 아래) 높은 수준의 각도 구성 요소에서 나는로드 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; 
    }); 
} 

은 마지막으로, 당신은 당신의 파일에 GAPI 스크립트 파일을 추가해야합니다. 하나가 GAPI를로드하기 전에 각도 두 세계가 들어가게 때문에

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

당신은 async또는defer 속성을 사용하지 않아야합니다. 난 강력하게을하지 않는 것이 좋습니다 ,

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

을하지만 :

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

이전 /main-app/src/assests 폴더에 gapi library의 로컬, 축소 된 사본을로드하고 가져 빠른 페이지로드 속도를 유지 제안 일을하고 있습니다. Google은 https://apis.google.com/js/api.js을 업데이트 할 수 있으며 클라이언트가 중단됩니다. 나는 이것에 두 번이나 붙잡 혔다. 결국 //apis.google.com/js/에서 가져 와서 차단 호출로 유지하는 것이 좋습니다.

+0

'@ types/gapi'와'@ types/gapi.auth2'를 설치 한 후, 어떻게 당신의 코드에서 그 타입을 사용합니까? 예를 들어 약속을'Promise '로 정의했습니다. 'Promise '과 같은 것을 어떻게 할 수 있습니까? – zanderle

+0

@zanderle은'gapi.auth2.GoogleAuth'로 사용합니다. 나처럼, angular-cli로 새로운 프로젝트를 시작한 경우, webpack은 gapi 네임 스페이스를 찾지 못하고 울고, tsconfig.app에 유형을 추가해야합니다. json. 앵귤러 팀은 자동'../ node_modules/@ types' 흠집이 필요 없다고 결정했기 때문에 번들을 할 때 webpack을 엉망으로 만듭니다. – GradientByte