65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Angular2、TypeScript、ASP.Net 和 SignalR 构建实时时钟

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.70/5 (8投票s)

2017 年 2 月 23 日

CPOL

11分钟阅读

viewsIcon

21005

在本文中,我们将看到如何使用 SignalR 和 Angular2 创建实时时钟,并将 Angular2 应用程序集成到 ASP.Net 中并查看其结果。

引言

在逐步创建实时时钟之前,最好先了解一些重要的术语和概念。

首先,我们来谈谈,

实时通信是什么意思?

实时通信(RTC)是指没有延迟的通信。当客户端通过服务器相互连接时,任何一个客户端发送消息后,服务器会立即将其推送到另一个或所有连接的客户端,没有任何延迟。就像我们使用的即时通讯服务,如 WhatsApp、IMO 和 Facebook Messenger 等流行服务。

它使用点对点连接,延迟最小,RTC 数据和消息在传输之间不会存储。

我认为这些关于实时通信的信息已经足够了,如果你想深入了解,可以在网上查阅相关内容。

接下来我们将讨论,

什么是 ASP.Net SignalR?

它是一个 ASP.Net 库,为 Web 应用程序添加实时功能。正如我们之前讨论的,在实时通信中,服务器接收数据后会立即推送到连接的客户端,而不会存储。

SignalR 提供了简单的 API,用于生成服务器到客户端的远程过程调用(RPC),这些调用可以从服务器端触发客户端的 JavaScript 函数,反之亦然,因为它支持双向通信。

SignalR 包含内置的丰富连接管理机制,并提供了连接、断开连接或重新连接的方法以供重写,以及分组和授权功能。

最后但同样重要的是,我们用于创建应用程序的技术是 Angular2。

什么是 Angular2?

Angular 2 是一个丰富的 UI 框架,用于构建移动和 Web 应用程序。它使用 JavaScript 构建。它在其第一版 Angular 1 的基础上进行了许多增强。它经过重新创建,现在使用 Angular2 开发应用程序更好,因为它具有以下扩展功能集。

  •           跨浏览器和跨平台兼容性
  •           双向数据绑定
  •           增强的路由支持
  •           模块化结构来管理你的代码
  •          ·卓越的社区支持
  •           高速和高性能
  •           功能齐全的工具,加快你的工作速度
  •          单元测试

使用代码实现

步骤 1

转到 文件  è  新建  è  项目,然后选择 Asp.Net Web 应用程序,命名项目和目的地后,按确定。

 

按下“确定”按钮后,将打开一个新窗口,用于选择新项目的模板。

在我们的案例中,我们使用的是“空”模板,并勾选了 MVC 复选框。

 

现在再次按下“确定”按钮以创建项目。

我们已成功创建了我们的 Web 应用程序。

第二步

现在我们首先将 SignalR 安装到创建的应用程序中。

为此,我们将右键单击项目并选择“管理 Nuget 包”。

 

Nuget 包管理器窗口打开,搜索 SignalR 并按下安装按钮以安装包。

 

现在,“审查更改”窗口打开,这些更改在安装后会反映在你的解决方案中。

 

按“确定”按钮继续。

此后,许可接受窗口打开,点击“我接受”以接受许可,否则点击“我拒绝”。

 

这是通过 Nuget 包管理器安装 SignalR 的最后一步,它可以安装项目所需的所有依赖项和脚本,并打开发生更改的项目文件夹。

您可以通过验证 Nuget 包管理器窗口中已安装的包上的勾选标记来确认包是否已安装。

 

步骤 3

下载并安装适用于 Windows 的 NodeJS。

前往 https://node.org.cn/en/ 并点击推荐版本以安装 Windows。

 

下载后,安装 Microsoft 安装程序文件并按照步骤在本地计算机上安装。

要检查它是否已成功安装在你的本地机器上,请打开命令提示符窗口并键入 node –v 并按 Enter 键,如果它返回 node 版本,如图像所示,则表示已成功安装。

 

通过输入命令 npm –v 验证 npm 是否已安装

 

步骤 4

通过向项目根目录添加新项来添加 OWIN 启动类。

 

文件创建后,在 Configuration 方法内部向文件添加以下代码。

app.MapSignalR();  

 

 

步骤 5

向项目添加 SignalR Hub 类,更好的方法是创建一个名为 Hubs 的文件夹并在其中添加 Hub 类。

我们首先创建一个名为 Hubs 的文件夹,然后右键单击该文件夹,选择“添加”  è  “SignalR Hub 类”,命名它,它会将 Hub 类添加到该文件夹。

 

我已经创建了一个名为 Clock 的 Hub 类。默认情况下,它将使用 Hello 方法创建。

复制并粘贴以下方法以遵循本教程。

 

	public void GetRealTime()   
	{  
	Clients.Caller.setRealTime(DateTime.Now.ToString("h:mm:ss tt"));  
	}  

 

现在让我们详细说明此方法,如您所见,GetRealTime 是一个 Hub 方法,它是服务器端方法。从客户端我们触发这个服务器端事件,然后它会进行远程过程调用,并通过调用 Clients.Caller.setRealTime 方法将响应发送回客户端,该方法随后在客户端用于接收响应并显示给客户端。

调用者指连接到集线器的调用客户端。

setRealTime 函数用于客户端,以广播和显示响应。

步骤 6

现在我们将着手为您的项目设置 Angular2 环境。

如果你想快速启动你的项目。你可以使用 Angular2 官方 github 帐户提供的现成 Angular2 项目,并克隆该项目以快速启动。

我已经列出了以下步骤来设置您的本地开发环境。

      1. 确保你已安装 node 和 npm。Node 用于客户端应用程序和构建工具,npm 包管理器用于安装 JavaScript 库。

      2. 在项目根目录创建 angular2 文件夹,然后在其中创建 app 文件夹,我们将只放置 angular2 代码,而在 angular2 文件夹中,我们将放置根目录所需的配置和其他文件。

      3. 创建配置文件。

                                  i. 首先,创建 tsconfig.json 文件。为此,按 Ctrl + Shift + A 或右键单击 angular2 文件夹,然后从上下文菜单中选择“添加新项”,出现新窗口,选择 json 文件并将其命名为 tsconfig.json,然后按“添加”创建文件。此文件的基本目的是为 typescript 编译配置设置环境。通过此文件,所有 typescript 文件都将转译为 Javascript。将以下代码添加到文件中。

{
"compilerOptions": {  
"target": "es5",  
"module": "system",  
"moduleResolution": "node",  
"sourceMap": true,  
"emitDecoratorMetadata": true,  
"experimentalDecorators": true,  
"removeComments": false,  
"noImplicitAny": false  
},  
"exclude": [
"node_modules",  
"typings/main",  
"typings/main.d.ts"  
   ]  
} 

                                ii. 其次,通过上述程序创建名为 typings.json 的文件,该文件可以识别您的 Angular 应用程序中的 TypeScript 定义文件。文件中定义了三种类型的 typing 文件。A) core-js b) jasmine 和 c) node。将以下代码复制到文件中。

{  
 "globalDependencies": {  
    "core-js": "registry:dt/core-js#0.0.0+20160602141332",  
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",  
    "node": "registry:dt/node#6.0.0+20160621231320"  
 }  
}  

                                iii. 第三,创建 package.json 文件,此文件包含我们的应用程序所需的包。这些包使用 node 包管理器安装和维护。将以下代码复制到文件中。

{  
    "name": "angular2realtimeclock",  
    "version": "1.0.0",  
    "scripts": {  
        "start": "concurrent \"npm run tsc:w\" \"npm run lite\" ",  
        "tsc": "tsc",  
        "tsc:w": "tsc -w",  
        "lite": "lite-server",  
        "typings": "typings",  
        "postinstall": "typings install"  
    },  
    "license": "ISC",  
    "dependencies": {  
        "angular2": "2.0.0-beta.7",  
        "systemjs": "0.19.22",  
        "es6-promise": "^3.0.2",  
        "es6-shim": "^0.33.3",  
        "reflect-metadata": "0.1.2",  
        "rxjs": "5.0.0-beta.2",  
        "zone.js": "0.5.15"  
    },  
    "devDependencies": {  
        "concurrently": "^2.0.0",  
        "lite-server": "^2.1.0",  
        "typescript": "^1.7.5",  
        "typings": "^0.6.8"  
    }  
}  

      4. 创建文件后,现在在 Windows 资源管理器中打开 angular2 文件夹,按下 Shift + 右键组合键并选择“在此处打开命令窗口”选项,或者通过命令指向此文件夹并输入 npm install 并按 Enter。

 

安装软件包后,它将在您安装的文件夹中创建 node_modules 和 typings 文件夹。

      5. 在成功安装软件包后,现在我们将为 Angular2 的源代码创建目录结构,因为在 Angular2 中所有内容都由组件组成,因此我们将创建一个由 Components、Classes、Services、Modules、Routing、Common 和 Shared 文件夹组成的基本通用文件夹结构站点,因此请在项目中创建所有这些文件夹。没有必要创建所有文件夹,您可以根据自己的需求开始,然后根据需要创建文件夹来扩展功能。

      6. 我们将从在 app 文件夹中创建基础组件及其模板开始。在 app 文件夹的根目录中创建名为 app.component.ts 的新 typescript 文件。

在文件中,首先从 anglar core 导入组件。

import {Component} from '@angular/core'

然后创建 @component 装饰器并添加选择器,我们将组件绑定到该选择器,然后是文件中简单 html 的模板,或者使用外部模板,通过 templateUrl 附加模板,如下所示。

@Component({  
    selector: 'my-app',  
    templateUrl: './app/app.component.html'  
})  

最后,导出该类,以便在其他类中导入时可以使用。

export class AppComponent { } 

      7. 接下来我们将创建名为 app.component.html 的应用程序组件模板,并将此代码放入其中。

<div id="wrapper"><router-outlet></router-outlet></div>

 

基本上 router-outlet 充当取决于当前路由状态的组件的占位符。

     8. 接下来创建 app.module,它作为所有模块的基础,您可以在其中导出组件类、值和函数,以便在其他模块中使用。复制并粘贴代码到 app.module 文件中。

import {  NgModule  } from '@angular/core';  
import {  BrowserModule } from '@angular/platform-browser';  
import {  AppComponent  } from './app.component';  
import {  routing } from './app.routes';  
import {  HttpModule,  JsonpModule  } from '@angular/http';  
import {  ClockComponent } from './components/clock/clock.component';  
import {  SignalRService  } from './services/signalRService';  
import { FormsModule  } from '@angular/forms';  
@NgModule({  
    imports: [  
        BrowserModule,  
        routing,  
        HttpModule,  
        JsonpModule,  
        FormsModule  
    ],  
    declarations: [  
        AppComponent,  
        ClockComponent  
    ],  
    providers: [  
        SignalRService  
    ],  
    bootstrap: [AppComponent]  
})  
export class AppModule {}

     9. 接下来我们将在 Angular 应用程序文件夹的根目录创建 main.ts 文件,它可以引导应用程序模块,粘贴以下代码。

import {  
    platformBrowserDynamic  
} from '@angular/platform-browser-dynamic';  
import {  
    AppModule  
} from './app.module';  
platformBrowserDynamic().bootstrapModule(AppModule);  

     10. 转到下一步,我们将创建 systemjs.config.js 文件,它可以映射应用程序的应用程序文件夹文件(将文件转译为 js),从特定路径加载包,并设置配置,最后我们将其放置在我们应用程序页面的主要入口点,主要是 index.html。

     11. 最后,我们将创建 index.html 文件,它是应用程序的主要入口点,我们在这里注册文件,如 shim、reflect、zone、system js 文件,并使用 System.import('您的映射应用程序文件夹的路径') 语句将以前生成的文件导入到主要入口点。在 index.html 中放置此行代码。

 
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1">  
    <link rel="stylesheet" href="styles.css">  
    <link href="app/app.component.css" rel="stylesheet" />  
    <!-- 1. Load libraries -->  
    <!-- Polyfill(s) for older browsers -->  
    <script src="node_modules/core-js/client/shim.min.js"></script>  
    <script src="node_modules/zone.js/dist/zone.js"></script>  
    <script src="node_modules/reflect-metadata/Reflect.js"></script>  
    <script src="node_modules/systemjs/dist/system.src.js"></script>  
    <!-- 2. Configure SystemJS -->  
    <script src="systemjs.config.js"></script>  
    <title>Angular 2 Realtime Clock</title>  
    <script src="../Scripts/jquery-1.10.2.min.js"></script>  
    <script src="../Scripts/jquery.signalR.js" type="text/javascript"></script>  
    <script>  
        System.import('app');  
    </script>  
 
<!-- 3. Display the application -->  
  

    <!-- headers -->  
    <!-- body -->  
    <my-app>Loading the app...</my-app>  
    <!-- footers-->  
 
  
  

在我们的案例中,还附加了满足我们需求的 signalR 和 jquery 客户端文件。

      12. 完成基本配置并安排好一切后,我们现在将创建使用 signalr 创建实时时钟的功能,如我们的组件、模型和服务。

      13. 所以首先我们将创建模型组件。将组件命名为 GetClockTime.ts,并将其放置在您应用程序的模型文件夹中,然后将以下代码粘贴到其中。

export class GetClockTime {  
    public Time: string;  
    constructor(time: string) {  
        this.Time = time;  
    }  
}  

在此代码块中,我们首先创建了可在其他组件中重用的导出类,并在构造函数中定义并初始化了一个类成员。

      14. 现在接下来我们将创建一些全局常量文件,因为常量是应用程序执行生命周期中值不能改变的变量。将文件命名为 app.constants.ts 并放置在通用文件夹中,然后粘贴以下代码。

export let CONFIGURATION = {  
    baseUrls: {  
        server: 'https://:50347/'  
    },  
}  

在此文件中,我们创建了导出的变量,并添加了要在 SignalR 服务中使用的服务器 URL。使用这些文件的基本目的是,一旦我们有了所有频繁使用的常量列表,就可以在一个地方更改它们,而不是单独在所有文件中更改。

      15. 在下一步中,我们将创建 SignalR 服务,它是整个过程的骨干。

 在服务文件夹中创建服务,并将以下代码粘贴到其中。

// import the packages  
import {  
    Injectable,  
    EventEmitter  
} from '@angular/core';  
import {  
    CONFIGURATION  
} from '../generic/app.constants';  
import {  
    GetClockTime  
} from '../models/getclocktime';  
// declare the global variables  
declare  
var $: any;  
@Injectable()  
export class SignalRService {  
    // Declare the variables  
    private proxy: any;  
    private proxyName: string = 'clock';  
    private connection: any;  
    // create the Event Emitter  
    public messageReceived: EventEmitter < GetClockTime > ;  
    public connectionEstablished: EventEmitter < Boolean > ;  
    public connectionExists: Boolean;  
    constructor() {  
        debugger;  
        // Constructor initialization  
        this.connectionEstablished = new EventEmitter < Boolean > ();  
        this.messageReceived = new EventEmitter < GetClockTime > ();  
        this.connectionExists = false;  
        // create hub connection  
        this.connection = $.hubConnection(CONFIGURATION.baseUrls.server);  
        // create new proxy as name already given in top  
        this.proxy = this.connection.createHubProxy(this.proxyName);  
        // register on server events  
        this.registerOnServerEvents();  
        // call the connecion start method to start the connection to send and receive events.  
        this.startConnection();  
    }  
    // method to hit from client  
    public sendTime() {  
        // server side hub method using proxy.invoke with method name pass as param  
        this.proxy.invoke('GetRealTime');  
    }  
    // check in the browser console for either signalr connected or not  
    private startConnection(): void {  
        this.connection.start().done((data: any) => {  
            console.log('Now connected ' + data.transport.name + ', connection ID= ' + data.id);  
            this.connectionEstablished.emit(true);  
            this.connectionExists = true;  
        }).fail((error: any) => {  
            console.log('Could not connect ' + error);  
            this.connectionEstablished.emit(false);  
        });  
    }  
    private registerOnServerEvents(): void {  
        debugger;  
        this.proxy.on('setRealTime', (data: GetClockTime) => {  
            console.log('received in SignalRService: ' + JSON.stringify(data));  
            this.messageReceived.emit(data);  
        });  
    }  
}  

 为了方便起见,我已经注释了每个部分。

      16. 此外,我们将创建实时时钟的主要组件。

 首先创建模块文件夹,然后创建名为 clock.component.ts 的组件文件来创建新组件。

 将此行代码放入其中。

import {  
    Component,  
    NgZone  
} from '@angular/core';  
import {  
    SignalRService  
} from '../../services/signalRService';  
import {  
    GetClockTime  
} from '../../models/getclocktime';  
// decorator section comprised of selector and view template  
@Component({  
    selector: 'clock-component',  
    templateUrl: './app/components/clock/clock.component.html'  
})  
export class ClockComponent {  
    // public variables declaration  
    public currentMessage: GetClockTime;  
    public allMessages: GetClockTime;  
    public canSendMessage: Boolean;  
    // constructor of the class to inject the service in the constuctor and call events.  
    constructor(private _signalRService: SignalRService, private _ngZone: NgZone) {  
        // this can subscribe for events  
        this.subscribeToEvents();  
        // this can check for conenction exist or not.  
        this.canSendMessage = _signalRService.connectionExists;  
        // this method call every second to tick and respone tansfered to client.  
        setInterval(() => {  
            this._signalRService.sendTime();  
        }, 1000);  
    }  
    private subscribeToEvents(): void {  
        // if connection exists it can call of method.  
        this._signalRService.connectionEstablished.subscribe(() => {  
            this.canSendMessage = true;  
        });  
        // finally our service method to call when response received from server event and transfer response to some variable to be shwon on the browser.  
        this._signalRService.messageReceived.subscribe((message: GetClockTime) => {  
            debugger;  
            this._ngZone.run(() => {  
                this.allMessages = message;  
            });  
        });  
    }  
}  

      17. 最后但同样重要的是,我们将为组件创建一个视图模板,其中将放置时钟以在浏览器中显示。

 创建 clock.component.html 文件作为视图,以向浏览器显示数据。

<style type="text/css">p {  
        color: #000;  
        font-size: 8.7em;  
        font-family: Helvetica, Arial;  
        padding-top: 0%;  
        margin-left: 25%;  
    }</style> 
    <div id="timediv">
<p>{{allMessages}}</p>
</div>

步骤 6:使用命令提示符 npm start 语句在浏览器上启动项目,或使用 visual studio f5 启动浏览器,然后键入 angular2 指向 angular2 应用程序。

最后,输出在这里。

  

关注点

这一切最好的地方在于尝试使用新技术创建相同的东西,而最好的地方在于为开发设置 angular2。

 

© . All rights reserved.