在angular 2打字稿中导入gapi.auth2
我试图在typescript中从谷歌gapi.auth2导入一些类或函数.但是下面的代码永远不会工作,即使我在typings目录中正确添加了gapi.auth2类型.
从’gapi.auth2’导入{GoogleAuth}; 我总是有错误: 错误TS2307:找不到模块’gapi.auth2′ 我应该使用一些相对目录搜索,例如’../../typings/gapi.auth2’? 或者也许我使用gapi的方式是完全错误的? 谢谢!
要将gapi和gapi.auth与Angular2一起使用,请使用NPM安装类型脚本定义.
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,您应该看到: main-app/ node_modules/ @types/ gapi/ gapi.auth2/ 编辑tsconfig.json以包含新的gapi和gapi.auth2类型(下面只是一个摘录): { "compileOnSave": false,"compilerOptions": { "types": ["gapi","gapi.auth2"] } } 此时我强烈建议您抓咖啡阅读Typescript Module Resolution,您可以直接跳到Node.js如何解析模块:
因此,您不需要在Angular2服务或组件中(或者在您使用gapi或gapi.auth2的任何位置)添加对类型定义的引用. 但是,如果你确实添加了对gapi或gapi.auth2 TypeScript定义的引用,它必须引用使用npm install安装的.ts文件(注意,你必须保持/// oherwise你会收到错误): /// <reference path="../../node_modules/@types/gapi/index.d.ts" /> 路径是相对的,因此您的文件可能会有所不同,具体取决于.ts文件相对于安装TypeScript定义的位置. 无论是添加显式引用还是使用TypeScript的Node模块解析机制,您仍然需要在.ts文件中声明变量,以便Angular2在编译时知道窗口gapi变量.添加声明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; 查看定义本身(https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/gapi/index.d.ts),仅导出函数.相反,接口是实现细节,因此它们不会被导出,并且对命名空间外的代码不可见. 在TypeScript documentation中使用其他JavaScript库值得阅读,以了解我们在所有这些工作中获得的成果. 接下来,使用您自己的函数加载gapi客户端(可能在Angular 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 }); }); }); } 这个功能非常重要,而且有充分理由…… 首先,请注意我们使用配置对象调用gapi.load而不仅仅是回调.可以使用GAPI reference状态: >库完成时调用的回调函数 使用配置选项允许我们在加载库超时或仅错误时拒绝Promise.根据我的经验,加载库比初始化失败更常见 – 这就是配置对象优于回调的原因. 其次,我们正在包装gapi.load this.zone.run(() => { // gapi.load }); NgZone.run is documented和州
这正是我们想要的,因为对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??密钥,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); }); }); } 请注意我们的朋友NgZone.run再次用于确保重新进入Angular Zone. 实际上,我将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属性,因为在gapi加载之前,任何一个都会导致Angular 2世界进入. <!-- This will not work. --> <html> <head> <script async defer src="https://apis.google.com/js/api.js"></script> 我之前建议通过在/ main-app / src / assests文件夹中加载gapi library的本地缩小副本并导入以下内容来快速保持页面加载速度: <html> <head> <script src="assets/api.js"></script> 但是,我强烈建议不要这样做. Google可能会更新https://apis.google.com/js/api.js,您的客户将会中断.我被这两次抓住了.最后,最好从//apis.google.com/js/导入并将其保留为阻止调用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |