在 Angular2 应用程序中使用 GeoFire
Using GeoFire in an Angular2 App
我正在尝试在我的 Angular2 (RC5) 应用程序中设置 GeoFire。我已经使用 npm 安装了 geofire 和 firebase,并配置了 systemjs 来导入它。这是我的 package.json:
{
"name": "MyProject",
"version": "0.1.0",
"scripts": {
"start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
"lite": "lite-server",
"postinstall": "typings install",
"tsc": "tsc",
"tsc:w": "tsc -w",
"typings": "typings"
},
"license": "ISC",
"dependencies": {
"@angular/common": "^2.0.0-rc.5",
"@angular/compiler": "^2.0.0-rc.5",
"@angular/core": "^2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "^2.0.0-rc.5",
"@angular/platform-browser-dynamic": "^2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.5",
"angular2-in-memory-web-api": "0.0.15",
"bootstrap": "^3.3.6",
"core-js": "^2.4.0",
"firebase": "^3.3.0",
"geofire": "^4.1.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"systemjs": "0.19.27",
"zone.js": "^0.6.12"
},
"devDependencies": {
"concurrently": "^2.0.0",
"lite-server": "^2.2.0",
"typescript": "^1.8.10",
"typings": "^1.0.4"
}
}
和我的 systemjs 配置文件:
var map = {
'app': 'app', // 'dist',
'@angular': 'node_modules/@angular',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
'firebase': 'node_modules/firebase',
'geofire': 'node_modules/geofire',
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
'firebase': { main: 'firebase.js', defaultExtension: 'js' },
'geofire': { main: 'dist/geofire.js', defaultExtension: 'js' },
};
最后我尝试在我的 app.component.ts 文件中导入 geofire,如下所示:
import * as GeoFire from "geofire";
但是在 运行 npm 开始转译并启动服务器时,出现以下错误:
➜ MyProject npm start
> MyProject@0.1.0 start /Users/max/Development/myproject
> tsc && concurrently "npm run tsc:w" "npm run lite"
app/app.component.ts(3,26): error TS2307: Cannot find module 'geofire'.
npm ERR! Darwin 15.5.0
npm ERR! argv "/usr/local/Cellar/node/5.10.1/bin/node" "/usr/local/bin/npm" "start"
npm ERR! node v5.10.1
npm ERR! npm v3.8.3
npm ERR! code ELIFECYCLE
npm ERR! MyProject@0.1.0 start: `tsc && concurrently "npm run tsc:w" "npm run lite" `
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the MyProject@0.1.0 start script 'tsc && concurrently "npm run tsc:w" "npm run lite" '.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the MyProject package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! tsc && concurrently "npm run tsc:w" "npm run lite"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs MyProject
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls MyProject
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /Users/max/Development/MyProject/npm-debug.log
这是我的 tsconfig:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
}
}
其余项目文件基于此处找到的 angular2 快速入门:
https://angular.io/guide/quickstart
有人知道如何让 tsc 找到模块并成功转译吗?
谢谢。最大
该快速入门教程遗漏了一个要点:SystemJS 和 TypeScript 是两个独立的工具,每个工具都有自己的配置。
在 systemjs 配置中添加 geofire 对 typescript 模块解析没有影响。看到这个 import
import * as GeoFire from "geofire";
tsc 尝试在通常可以找到 javascript 模块类型的地方找到 geofire.ts,并给出一个错误,因为它不在那里。
有三种不同的方法可以解决这个问题。
无论如何,systemjs.config.js中的geofire
包配置必须声明其格式为global
,像这样:
'geofire': {
main: 'dist/geofire.js',
defaultExtension: 'js',
meta: {'dist/geofire.js': {format: 'global'}}
},
第一个解决方案是使用环境模块自己为 geofire 创建尽可能简单的类型声明。
在应用程序文件夹中创建 geofire.d.ts
文件:
declare namespace geofire {
function GeoFire(firebaseRef: any): void;
}
declare module 'geofire' {
export = geofire;
}
这足以编译 import 语句,并调用类型检查:
var geoFire = new GeoFire(firebaseRef);
打字稿 2.0 的注意事项
对于打字稿 2.0,上面的代码不起作用。您必须使用特定于打字稿的 import =
语法
import GeoFire = require('geofire');
并将 geofire.d.ts
中的定义更改为:
declare module 'geofire' {
function GeoFire(firebaseRef: any): void;
export = GeoFire;
}
另一种可能的解决方法是对使用 TypeScript API 的 SystemJS 使用 plugin 来调用 typescript 并挂钩其模块解析,以便它考虑 SystemJS 配置。使用该插件,该导入将在运行时在浏览器中运行,但从命令行调用 tsc 仍会出现相同的错误。
第三种方式是使用SystemJS导入geofireAPI,而不是app.component.ts中的import语句:
import { Component } from '@angular/core';
declare var SystemJS : any;
var GeoFirePromise = SystemJS.import('geofire');
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent {
constructor() { // or wherever you need to use geofire
GeoFirePromise.then(function(GeoFire: any) {
console.log(typeof GeoFire);
});
}
}
请注意 SystemJS.import
returns 一个必须加载的承诺 geofire.js,所以任何你想使用它的地方都必须这样做
GeoFirePromise.then(function(GeoFire: any) {
如果这样不方便,你可以只声明全局 GeoFire 变量
declare var GeoFire: any;
并使用 HTML 中的脚本标记加载 geofire.js,如 this post on ionic forum 中所述。然后,您就不需要将 geofire 添加到 systemjs.config.js.
注意,我仍然不是 TypeScript 专家,这是我第一次涉足类型定义等,但经过漫长的一天工作后,我似乎得到了一些有用的东西(至少对于我的设置而言)。我正在使用 Ionic 2 RC2、Angular2 2.1.1、Geofire 4.1.2。构建使用 webpack。我在我的应用程序目录中使用以下内容创建了 geofire.d.ts
:
declare module 'geofire' {
type EventType = 'ready' | 'key_entered' | 'key_exited' | 'key_moved';
interface GeoQueryCriteria {
center: number[];
radius: number;
}
interface GeoQueryUpdateCriteria {
center?: number[];
radius?: number;
}
interface GeoCallbackRegistration {
cancel();
}
interface GeoQuery {
center(): number[];
radius(): number;
updateCriteria(criteria: GeoQueryUpdateCriteria);
on(eventType: EventType, callback: (key:string, location: number[], distance: number) => void): GeoCallbackRegistration;
cancel();
}
class GeoFire {
constructor(ref: any);
ref(): any;
set(key: string, loc: number[]): Promise<void>;
get(key: string): Promise<number[]>;
remove(key: string): Promise<void>;
query(criteria: GeoQueryCriteria): GeoQuery;
static distance(location1: number[], location2: number[]);
}
export = GeoFire;
}
终于在我的 Service/Page 中,我可以像这样导入 GeoFire:
import GeoFire from 'geofire';
请注意导入的 确切 语法没有大括号 {}。我尝试了很多方法让它以不同的方式工作,但我认为 javascript 的编写方式,这就是它必须完成的方式。我找到了可以消除编译错误但在运行时失败的方法 ('no constructor named...'),或者它会在编译时识别构造函数但不识别为类型。
我只为 public API 创建了它,因此如果您出于某种原因尝试扩展 GeoFire,请注意可能与此定义文件中未公开的其他方法发生名称冲突。
如果这对您有帮助,请告诉我,我会将其贡献给 DefinitelyTyped 这样就没有其他人会经历我(显然还有其他拥有 340+ 观看次数)的痛苦。
我正在尝试在我的 Angular2 (RC5) 应用程序中设置 GeoFire。我已经使用 npm 安装了 geofire 和 firebase,并配置了 systemjs 来导入它。这是我的 package.json:
{
"name": "MyProject",
"version": "0.1.0",
"scripts": {
"start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
"lite": "lite-server",
"postinstall": "typings install",
"tsc": "tsc",
"tsc:w": "tsc -w",
"typings": "typings"
},
"license": "ISC",
"dependencies": {
"@angular/common": "^2.0.0-rc.5",
"@angular/compiler": "^2.0.0-rc.5",
"@angular/core": "^2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "^2.0.0-rc.5",
"@angular/platform-browser-dynamic": "^2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
"@angular/router-deprecated": "2.0.0-rc.2",
"@angular/upgrade": "2.0.0-rc.5",
"angular2-in-memory-web-api": "0.0.15",
"bootstrap": "^3.3.6",
"core-js": "^2.4.0",
"firebase": "^3.3.0",
"geofire": "^4.1.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"systemjs": "0.19.27",
"zone.js": "^0.6.12"
},
"devDependencies": {
"concurrently": "^2.0.0",
"lite-server": "^2.2.0",
"typescript": "^1.8.10",
"typings": "^1.0.4"
}
}
和我的 systemjs 配置文件:
var map = {
'app': 'app', // 'dist',
'@angular': 'node_modules/@angular',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
'firebase': 'node_modules/firebase',
'geofire': 'node_modules/geofire',
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.js', defaultExtension: 'js' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
'firebase': { main: 'firebase.js', defaultExtension: 'js' },
'geofire': { main: 'dist/geofire.js', defaultExtension: 'js' },
};
最后我尝试在我的 app.component.ts 文件中导入 geofire,如下所示:
import * as GeoFire from "geofire";
但是在 运行 npm 开始转译并启动服务器时,出现以下错误:
➜ MyProject npm start
> MyProject@0.1.0 start /Users/max/Development/myproject
> tsc && concurrently "npm run tsc:w" "npm run lite"
app/app.component.ts(3,26): error TS2307: Cannot find module 'geofire'.
npm ERR! Darwin 15.5.0
npm ERR! argv "/usr/local/Cellar/node/5.10.1/bin/node" "/usr/local/bin/npm" "start"
npm ERR! node v5.10.1
npm ERR! npm v3.8.3
npm ERR! code ELIFECYCLE
npm ERR! MyProject@0.1.0 start: `tsc && concurrently "npm run tsc:w" "npm run lite" `
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the MyProject@0.1.0 start script 'tsc && concurrently "npm run tsc:w" "npm run lite" '.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the MyProject package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! tsc && concurrently "npm run tsc:w" "npm run lite"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs MyProject
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls MyProject
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /Users/max/Development/MyProject/npm-debug.log
这是我的 tsconfig:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
}
}
其余项目文件基于此处找到的 angular2 快速入门:
https://angular.io/guide/quickstart
有人知道如何让 tsc 找到模块并成功转译吗?
谢谢。最大
该快速入门教程遗漏了一个要点:SystemJS 和 TypeScript 是两个独立的工具,每个工具都有自己的配置。
在 systemjs 配置中添加 geofire 对 typescript 模块解析没有影响。看到这个 import
import * as GeoFire from "geofire";
tsc 尝试在通常可以找到 javascript 模块类型的地方找到 geofire.ts,并给出一个错误,因为它不在那里。
有三种不同的方法可以解决这个问题。
无论如何,systemjs.config.js中的geofire
包配置必须声明其格式为global
,像这样:
'geofire': {
main: 'dist/geofire.js',
defaultExtension: 'js',
meta: {'dist/geofire.js': {format: 'global'}}
},
第一个解决方案是使用环境模块自己为 geofire 创建尽可能简单的类型声明。
在应用程序文件夹中创建 geofire.d.ts
文件:
declare namespace geofire {
function GeoFire(firebaseRef: any): void;
}
declare module 'geofire' {
export = geofire;
}
这足以编译 import 语句,并调用类型检查:
var geoFire = new GeoFire(firebaseRef);
打字稿 2.0 的注意事项
对于打字稿 2.0,上面的代码不起作用。您必须使用特定于打字稿的 import =
语法
import GeoFire = require('geofire');
并将 geofire.d.ts
中的定义更改为:
declare module 'geofire' {
function GeoFire(firebaseRef: any): void;
export = GeoFire;
}
另一种可能的解决方法是对使用 TypeScript API 的 SystemJS 使用 plugin 来调用 typescript 并挂钩其模块解析,以便它考虑 SystemJS 配置。使用该插件,该导入将在运行时在浏览器中运行,但从命令行调用 tsc 仍会出现相同的错误。
第三种方式是使用SystemJS导入geofireAPI,而不是app.component.ts中的import语句:
import { Component } from '@angular/core';
declare var SystemJS : any;
var GeoFirePromise = SystemJS.import('geofire');
@Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent {
constructor() { // or wherever you need to use geofire
GeoFirePromise.then(function(GeoFire: any) {
console.log(typeof GeoFire);
});
}
}
请注意 SystemJS.import
returns 一个必须加载的承诺 geofire.js,所以任何你想使用它的地方都必须这样做
GeoFirePromise.then(function(GeoFire: any) {
如果这样不方便,你可以只声明全局 GeoFire 变量
declare var GeoFire: any;
并使用 HTML 中的脚本标记加载 geofire.js,如 this post on ionic forum 中所述。然后,您就不需要将 geofire 添加到 systemjs.config.js.
注意,我仍然不是 TypeScript 专家,这是我第一次涉足类型定义等,但经过漫长的一天工作后,我似乎得到了一些有用的东西(至少对于我的设置而言)。我正在使用 Ionic 2 RC2、Angular2 2.1.1、Geofire 4.1.2。构建使用 webpack。我在我的应用程序目录中使用以下内容创建了 geofire.d.ts
:
declare module 'geofire' {
type EventType = 'ready' | 'key_entered' | 'key_exited' | 'key_moved';
interface GeoQueryCriteria {
center: number[];
radius: number;
}
interface GeoQueryUpdateCriteria {
center?: number[];
radius?: number;
}
interface GeoCallbackRegistration {
cancel();
}
interface GeoQuery {
center(): number[];
radius(): number;
updateCriteria(criteria: GeoQueryUpdateCriteria);
on(eventType: EventType, callback: (key:string, location: number[], distance: number) => void): GeoCallbackRegistration;
cancel();
}
class GeoFire {
constructor(ref: any);
ref(): any;
set(key: string, loc: number[]): Promise<void>;
get(key: string): Promise<number[]>;
remove(key: string): Promise<void>;
query(criteria: GeoQueryCriteria): GeoQuery;
static distance(location1: number[], location2: number[]);
}
export = GeoFire;
}
终于在我的 Service/Page 中,我可以像这样导入 GeoFire:
import GeoFire from 'geofire';
请注意导入的 确切 语法没有大括号 {}。我尝试了很多方法让它以不同的方式工作,但我认为 javascript 的编写方式,这就是它必须完成的方式。我找到了可以消除编译错误但在运行时失败的方法 ('no constructor named...'),或者它会在编译时识别构造函数但不识别为类型。
我只为 public API 创建了它,因此如果您出于某种原因尝试扩展 GeoFire,请注意可能与此定义文件中未公开的其他方法发生名称冲突。
如果这对您有帮助,请告诉我,我会将其贡献给 DefinitelyTyped 这样就没有其他人会经历我(显然还有其他拥有 340+ 观看次数)的痛苦。