我试图在 typescript 中从 Google gapi.auth2 导入一些类或函数。但是即使我在打字目录中正确添加了 gapi.auth2 类型,下面的代码也永远无法工作。import { GoogleAuth } from 'gapi.auth2';
我总是有错误:Error TS2307: Cannot find module 'gapi.auth2'
我应该使用一些相对目录搜索,例如'../../typings/gapi.auth2'吗?
或者我使用gapi的方式是完全错误的?
谢谢!
最佳答案
使用 gapi
和 gapi.auth
对于 Angular2,使用 NPM 安装类型脚本定义。
npm install --save @types/gapi
npm install --save @types/gapi.auth2
这将安装两个包,@types/gapi和 @types/gapi.auth2到 node_modules
文件夹并将配置保存在 package.json
.检查您的
node_modules
文件夹以检查它们是否正确安装。如果您的 Angular 应用程序被称为“主应用程序”,您应该看到:main-app/
node_modules/
@types/
gapi/
gapi.auth2/
red pill and blue pill设想:gapi
或 gapi.auth2
到 "types": []
tsconfig.json
中的编译器选项|因为 @types
编译过程中包含包。 node_modules/@types
(任何封闭文件夹的)被认为是可见的。 types
已经指定,TSConfig Reference说明您必须添加 gapi
或 gapi.auth2
否则默认情况下不会包含它们。在这一节中,编辑 tsconfig.json
包括新的 gapi
和 gapi.auth2
类型:{
"compilerOptions": {
"types": ["jest", "lodash", "gapi", "gapi.auth2"]
}
}
此时,如果你有足够的动力,可以阅读Typescript Module Resolution ,可以直接跳到 Node.js 如何解析模块 :Node will look for your modules in special folders named
node_modules
. Anode_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 eachnode_modules
until it finds the module you tried to load.
出于这个原因,您不需要在 Angular2 服务或组件中添加对类型定义的引用(或在您使用
gapi
或 gapi.auth2
的任何地方)。但是,如果您确实添加了对
gapi
的引用或 gapi.auth2
TypeScript 定义,它必须引用 .ts
使用 npm install
安装的文件(注意,你必须保留 ///
否则你会得到一个错误):/// <reference path="../../node_modules/@types/gapi/index.d.ts" />
路径是相对的,因此您的路径可能会因.ts
的位置而异。文件与您安装 TypeScript 定义的位置有关。无论您是添加了显式引用还是使用了 TypeScript 的 Node 模块解析机制,您仍然需要在
.ts
中声明您的变量。文件,以便 Angular 知道窗口 gapi
编译时变量。添加 declare var gapi: any;
给您的 .ts
文件,但不要将其放在类定义中。我把我的放在任何进口的下面:// 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;
使用其他 JavaScript 库 在 TypeScript documentation值得一读以了解我们从所有这些工作中得到了什么。接下来,加载
gapi
来自您自己的函数的客户端(可能在 Angular 服务中): 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可以使用状态:
加载。
对于这种方法。只需要回调。
使用配置选项允许我们拒绝 加载库超时或只是错误时的 Promise。根据我的经验,加载库比初始化它失败的频率更高——这就是为什么配置对象比回调更好的原因。
其次,我们正在包装
gapi.load
在this.zone.run(() => {
// gapi.load
});
NgZone.run is documented和状态Running functions via
zone.run
allows you to reenter Angular zone from a task that was executed outside of the Angular zone [...]
这正是我们在调用
gapi.load
后想要的。离开 Angular 区域。忽略这一点可能会导致很难调试的非常时髦的结果。三、
loadClient()
返回一个已解决的 promise - 允许调用者选择他们如何处理 gapi.load
.例如,如果我们的 loadClient
方法属于 Angular 服务,apiLoaderServce
,组件可以使用 ngOnInit
加载 gapi
:ngOnInit(): void {
this.apiLoaderService.loadClient().then(
result => this.apiLoaded = true,
err => this.apiLoaded = false
);
}
曾经gapi.load
已被调用,gapi.client
将准备就绪,您应该使用它来使用您的 API key 、OAuth 客户端 ID、范围和 API 发现文档来初始化 JavaScript 客户端: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);
});
});
}
通知我们的 friend NgZone.run再次使用以确保重新输入 Angular 区域。在实践中,我添加
loadClient()
和 initClient()
到 Angular 服务。在高级 Angular 组件(通常就在 app 组件下方)中,我在 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 脚本文件添加到您的文件中。<html>
<head>
<script src="https://apis.google.com/js/api.js"></script>
您不得使用 async
或 defer
属性,因为它们会导致 Angular 世界在 gapi 库加载之前进入。<!-- This will not work. -->
<html>
<head>
<script async defer src="https://apis.google.com/js/api.js"></script>
我之前建议通过加载 gapi library 的本地缩小副本来保持快速页面加载速度。在 /main-app/src/assests
文件夹和导入: <html>
<head>
<script src="assets/api.js"></script>
然而,我强烈推荐 不做这个。谷歌可能会更新 https://apis.google.com/js/api.js你的客户会崩溃。我已经被这两次捕获了。最后最好从 //apis.google.com/js/
导入并将其保留为阻塞调用。
关于typescript - 在angular 2 typescript 中导入gapi.auth2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38091215/