- 使用Nodejs创建服务器
- 使用Express创建restful的http服务
- 监控服务器文件的变化
{
"compilerOptions": { "module": "commonjs","target": "es5","emitDecoratorMetadata": true,"experimentalDecorators": true,"outDir": "build","lib": ["es6"] },"exclude": [ "node_modules" ] }
@H_404_0@配置一下webstorm
@H_404_0@Settings,Languages & Frameworks,TypeScript,把Enable TypeScript Compiler前边的对勾打上。
@H_404_0@在server中建一个文件server,在里边新建一个hello_server.ts文件
import * as http from 'http'
const server=http.createServer(function (request,response) { response.end('Hello World\n'); }).listen(8888);
@H_404_0@执行node build/hello_server.js
@H_404_0@之后访问http://localhost:8888/
@H_404_0@就会看到页面显示Hello World
@H_404_0@执行cnpm install express –save 来安装express框架
@H_404_0@执行cnpm install @types/express –save
@H_404_0@在第二个server中新建一个auction_server.ts
import * as express from 'express';
const app=express();
app.get('/',(req,res)=>{ res.send("Hello Express"); }); app.get('/products',res)=>{ res.send("接收到商品查询请求"); }); const server=app.listen(8888,"localhost",()=>{ console.log("服务器已启动,地址是:http://localhost:8888"); });
@H_404_0@执行node build/auction_server.js
@H_404_0@执行cnpm install -g nodemon 可以改变文件后不用重启服务
@H_404_0@执行nodemon build/auction_server.js 来启动服务
@H_404_0@修改auction_server.ts
import * as express from 'express';
const app=express();
export class Product {
constructor(public id: number,public title: string,public price: number,public rating: number,public desc: string,public categories: Array<string>) {
}
}
const products:Product[]= [
new Product(1,'第一个商品',1.99,3.5,'这是第一个商品,是我在学习慕课网Angular入门实战时创建的',['电子产品']),new Product(2,'第二个商品',2.99,2.5,'这是第二个商品,是我在学习慕课网Angular入门实战时创建的',['电子产品','硬件设备']),new Product(3,'第三个商品',3.99,4.5,'这是第三个商品,是我在学习慕课网Angular入门实战时创建的',new Product(4,'第四个商品',4.99,1.5,'这是第四个商品,是我在学习慕课网Angular入门实战时创建的',new Product(5,'第五个商品',5.99,'这是第五个商品,是我在学习慕课网Angular入门实战时创建的',new Product(6,6.99,'这是第六个商品,是我在学习慕课网Angular入门实战时创建的',['电子产品'])
];
app.get('/',res)=>{ res.json(products); }); const server=app.listen(8888,()=>{ console.log("服务器已启动,地址是:http://localhost:8888"); });
@H_404_0@然后访问http://localhost:8888/products
@H_404_0@添加一个方法
app.get('/product/:id',res) => { res.json(products.find((product) => product.id == req.params.id)); });
@H_404_0@然后访问http://localhost:8888/product/3
Http通讯@H_79_301@
@H_404_0@新建一个项目client
@H_404_0@打开node_modules/@angular/http/src/http.d.ts
import { Observable } from 'rxjs/Observable';
import { RequestOptions } from './base_request_options';
import { ConnectionBackend,RequestOptionsArgs } from './interfaces';
import { Request } from './static_request';
import { Response } from './static_response';
/** * Performs http requests using `XMLHttpRequest` as the default backend. * * `Http` is available as an injectable class,with methods to perform http requests. Calling * `request` returns an `Observable` which will emit a single {@link Response} when a * response is received. * * ### Example * * ```typescript * import {Http,HTTP_PROVIDERS} from '@angular/http'; * import 'rxjs/add/operator/map' * @Component({ * selector: 'http-app',* viewProviders: [HTTP_PROVIDERS],* templateUrl: 'people.html' * }) * class PeopleComponent { * constructor(http: Http) { * http.get('people.json') * // Call map on the response observable to get the parsed people object * .map(res => res.json()) * // Subscribe to the observable to get the parsed people object and attach it to the * // component * .subscribe(people => this.people = people); * } * } * ``` * * * ### Example * * ``` * http.get('people.json').subscribe((res:Response) => this.people = res.json()); * ``` * * The default construct used to perform requests,`XMLHttpRequest`,is abstracted as a "Backend" ( * {@link XHRBackend} in this case),which could be mocked with dependency injection by replacing * the {@link XHRBackend} provider,as in the following example: * * ### Example * * ```typescript * import {BaseRequestOptions,Http} from '@angular/http'; * import {MockBackend} from '@angular/http/testing'; * var injector = Injector.resolveAndCreate([ * BaseRequestOptions,* MockBackend,* {provide: Http,useFactory: * function(backend,defaultOptions) { * return new Http(backend,defaultOptions); * },* deps: [MockBackend,BaseRequestOptions]} * ]); * var http = injector.get(Http); * http.get('request-from-mock-backend.json').subscribe((res:Response) => doSomething(res)); * ``` * * @experimental */
export declare class Http {
protected _backend: ConnectionBackend;
protected _defaultOptions: RequestOptions;
constructor(_backend: ConnectionBackend,_defaultOptions: RequestOptions);
/** * Performs any type of http request. First argument is required,and can either be a url or * a {@link Request} instance. If the first argument is a url,an optional {@link RequestOptions} * object can be provided as the 2nd argument. The options object will be merged with the values * of {@link BaseRequestOptions} before performing the request. */
request(url: string | Request,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `get` http method. */
get(url: string,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `post` http method. */
post(url: string,body: any,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `put` http method. */
put(url: string,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `delete` http method. */
delete(url: string,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `patch` http method. */
patch(url: string,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `head` http method. */
head(url: string,options?: RequestOptionsArgs): Observable<Response>;
/** * Performs a request with `options` http method. */
options(url: string,options?: RequestOptionsArgs): Observable<Response>;
}
/** * @experimental */
export declare class Jsonp extends Http {
constructor(backend: ConnectionBackend,defaultOptions: RequestOptions);
/** * Performs any type of http request. First argument is required,an optional {@link RequestOptions} * object can be provided as the 2nd argument. The options object will be merged with the values * of {@link BaseRequestOptions} before performing the request. * * @security Regular XHR is the safest alternative to JSONP for most applications,and is * supported by all current browsers. Because JSONP creates a `<script>` element with * contents retrieved from a remote source,attacker-controlled data introduced by an untrusted * source could expose your application to XSS risks. Data exposed by JSONP may also be * readable by malicIoUs third-party websites. In addition,JSONP introduces potential risk for * future security issues (e.g. content sniffing). For more detail,see the * [Security Guide](http://g.co/ng/security). */
request(url: string | Request,options?: RequestOptionsArgs): Observable<Response>;
}
@H_404_0@http服务就是一个标准的TypeScript的类,跟我们自己写的服务是一样的。
get(url: string,options?: RequestOptionsArgs): Observable<Response>;
@H_404_0@get就是发get请求的,post就是发post请求的,put就是发put请求的。。。
@H_404_0@url就是发订单请求的 路径,这是必须的参数
@H_404_0@options是可选参数,
@H_404_0@每个方法都返回一个Observable,也就是可观测的流,流中的元素类型是Response,通过订阅这个流来获取服务端响应的数据,RequestOptionsArgs定义了一组与请求相关的参数
export interface RequestOptionsArgs {
url?: string | null;
method?: string | RequestMethod | null;
/** @deprecated from 4.0.0. Use params instead. */
search?: string | URLSearchParams | {
[key: string]: any | any[];
} | null;
params?: string | URLSearchParams | {
[key: string]: any | any[];
} | null;
headers?: Headers | null;
body?: any;
withCredentials?: boolean | null;
responseType?: ResponseContentType | null;
}
@H_404_0@其中url,method,body可以由调用的方法来决定
@H_404_0@一般只会用这个方法来传递请求头headers
@H_404_0@新建一个组件ng g component product
@H_404_0@修改product.component.ts
import {Component,OnInit} from '@angular/core';
import {Http} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
@Component({
selector: 'app-product',templateUrl: './product.component.html',styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
dataSource: Observable<any>;//用来接收http服务返回的流
products: Array<any> = [];
constructor(private http: Http) {
this.dataSource=this.http.get('/api/products')
.map((res)=>res.json()); } ngOnInit() { this.dataSource.subscribe( (data)=>this.products=data ); } }
@H_404_0@修改product.component.html
<p>
商品信息
</p>
<ul>
<li *ngFor="let product of products">
{{product.title}}
</li>
</ul>
@H_404_0@修改app.component.html
<app-product></app-product>
@H_404_0@在client下新建一个配置文件proxy.conf.json。当头路径为/api时,都转发为localhost:8888
{
"/api":{ "target":"http://localhost:8888" } }
@H_404_0@修改package.json,让服务启动的时候加载proxy.conf.json文件
"start": "ng serve --proxy-config proxy.conf.json",
@H_404_0@把服务端的地址前面都加上/api
app.get('/api/products',app.get('/api/product/:id',
@H_404_0@启动服务,访问http://localhost:4200/,就可以看到商品的名称了。
@H_404_0@http请求的发送并不是由get方法触发的而是由subscribe触发的
@H_404_0@另一种通过管道的写法
@H_404_0@修改product.component.ts
export class ProductComponent implements OnInit {
products: Observable<any>;
constructor(private http: Http) {
this.products=this.http.get('/api/products')
.map((res)=>res.json());
}
ngOnInit() {
}
}
@H_404_0@修改product.component.html
<p>
商品信息
</p>
<ul>
<li *ngFor="let product of products | async">
{{product.title}}
</li>
</ul>
@H_404_0@添加请求头
import {Component,OnInit} from '@angular/core';
import {Http,Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
@Component({
selector: 'app-product',styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
products: Observable<any>;
constructor(private http: Http) {
let myHeaders: Headers = new Headers();
myHeaders.append("Authorization","Basic 123456")
this.products = this.http.get('/api/products',{headers: myHeaders})
.map((res) => res.json()); } ngOnInit() { } }
WebSocket通讯@H_79_301@
@H_404_0@http协议在同一时间是能是发送请求或者接收响应。不能同时进行。
@H_404_0@而websocket协议可以在发送请求的时候也可以接收数据。
@H_404_0@是一个长连接协议,不需要在每次发送或接收时建立连接,延迟更低
@H_404_0@不需要每次都携带一些连接相关的信息,因此传递的信息少。
@H_404_0@在server项目中安装ws相关的包cnpm install ws –save
@H_404_0@执行cnpm install @types/ws –save-dev
@H_404_0@websocket不是一个请求响应的协议。服务器和客户端都可以主动发送请求。
@H_404_0@修改server项目中的auction_server.ts
import {Server} from 'ws';
const wsServer = new Server({port: 8085});
wsServer.on('connection',websocket => {
websocket.send("这个消息是服务器主动推送的");
});
@H_404_0@在机器的8085端口创建一个服务器,当有任何一个客户端连接到这个服务器的时候,给这个客户端推送一个消息。
@H_404_0@htt通信p是通过订阅http服务的get或post方法返回的流来处理服务器的响应数据
@H_404_0@但是Angular并没有提供一个类似http服务端的类来从websocket中产生一个流,所以要自己写一个服务来返回流。
@H_404_0@在client项目新生成一个服务ng g service shared/webSocket
@H_404_0@修改web-socket.service.ts
import {Injectable} from '@angular/core';
import {Observable} from "rxjs";
@Injectable()
export class WebSocketService {
ws: WebSocket;
constructor() {
}
/** * 这个方法返回一个流,流中包括服务器推送的消息 * @param {string} url * @returns {Observable<any>} */
createObservableSocket(url: string): Observable<any> {
//创建一个websocket对象,这个对象会根据传进去的url去连接指定的websocket服务器
this.ws = new WebSocket(url);
return new Observable(
observer => {
this.ws.onmessage = (event) => observer.next(event.data);
this.ws.onerror = (event) => observer.error(event);
this.ws.onclose = (event) => observer.complete();
}
);
}
//向服务器发送一个消息
sendMessage(message: string) {
this.ws.send(message);
}
}
@H_404_0@新建一个组件ng g component webSocket
@H_404_0@修改web-socket.component.ts
import {Component,OnInit} from '@angular/core';
import {WebSocketService} from "../shared/web-socket.service";
@Component({
selector: 'app-web-socket',templateUrl: './web-socket.component.html',styleUrls: ['./web-socket.component.css']
})
export class WebSocketComponent implements OnInit {
constructor(private wsService: WebSocketService) {
}
ngOnInit() {
this.wsService.createObservableSocket("ws://localhost:8085")
.subscribe(
data=>console.log(data),err=>console.log(err),()=>console.log("流已经结束")
);
}
sendMessageToServer(){
this.wsService.sendMessage("Hello from client");
}
}
@H_404_0@修改web-socket.component.html
<button (click)="sendMessageToServer()">向服务器发送数据</button>
@H_404_0@修改app.component.html
<app-product></app-product>
<app-web-socket></app-web-socket>
@H_404_0@修改app.module.ts
providers: [WebSocketService],
@H_404_0@修改server中的auction_server.ts
const wsServer = new Server({port: 8085});
wsServer.on('connection',websocket => {
websocket.send("这个消息是服务器主动推送的");
websocket.on("message",message=>{
console.log("接受到消息:"+message)
})
});
@H_404_0@之后访问http://localhost:4200/,查看浏览器的控制台会看到“这个消息是服务器主动推送的”。
@H_404_0@然后点击按钮,查看server项目的控制台会看到“接受到消息:Hello from client”
@H_404_0@现在这种情况是只有在客户端连接的时候服务器才会推送消息,如何在任何需要的时候推送消息呢?
@H_404_0@修改auction_server.ts,添加
setInterval(()=>{ if(wsServer.clients){ wsServer.clients.forEach(client=>{ client.send("这是定时推送"); }) } },2000);
@H_404_0@遍历每个客户端,每2秒给每个客户端推送消息
import {Server} from 'ws';
const wsServer = new Server({port: 8085});
wsServer.on('connection',websocket => {
websocket.send("这个消息是服务器主动推送的");
});
@H_404_0@在机器的8085端口创建一个服务器,当有任何一个客户端连接到这个服务器的时候,给这个客户端推送一个消息。
@H_404_0@htt通信p是通过订阅http服务的get或post方法返回的流来处理服务器的响应数据
@H_404_0@但是Angular并没有提供一个类似http服务端的类来从websocket中产生一个流,所以要自己写一个服务来返回流。
@H_404_0@在client项目新生成一个服务ng g service shared/webSocket
@H_404_0@修改web-socket.service.ts
import {Injectable} from '@angular/core';
import {Observable} from "rxjs";
@Injectable()
export class WebSocketService {
ws: WebSocket;
constructor() {
}
/** * 这个方法返回一个流,流中包括服务器推送的消息 * @param {string} url * @returns {Observable<any>} */
createObservableSocket(url: string): Observable<any> {
//创建一个websocket对象,这个对象会根据传进去的url去连接指定的websocket服务器
this.ws = new WebSocket(url);
return new Observable(
observer => {
this.ws.onmessage = (event) => observer.next(event.data);
this.ws.onerror = (event) => observer.error(event);
this.ws.onclose = (event) => observer.complete();
}
);
}
//向服务器发送一个消息
sendMessage(message: string) {
this.ws.send(message);
}
}
@H_404_0@新建一个组件ng g component webSocket
@H_404_0@修改web-socket.component.ts
import {Component,OnInit} from '@angular/core';
import {WebSocketService} from "../shared/web-socket.service";
@Component({
selector: 'app-web-socket',templateUrl: './web-socket.component.html',styleUrls: ['./web-socket.component.css']
})
export class WebSocketComponent implements OnInit {
constructor(private wsService: WebSocketService) {
}
ngOnInit() {
this.wsService.createObservableSocket("ws://localhost:8085")
.subscribe(
data=>console.log(data),err=>console.log(err),()=>console.log("流已经结束")
);
}
sendMessageToServer(){
this.wsService.sendMessage("Hello from client");
}
}
@H_404_0@修改web-socket.component.html
<button (click)="sendMessageToServer()">向服务器发送数据</button>
@H_404_0@修改app.component.html
<app-product></app-product>
<app-web-socket></app-web-socket>
@H_404_0@修改app.module.ts
providers: [WebSocketService],
@H_404_0@修改server中的auction_server.ts
const wsServer = new Server({port: 8085});
wsServer.on('connection',websocket => {
websocket.send("这个消息是服务器主动推送的");
websocket.on("message",message=>{
console.log("接受到消息:"+message)
})
});
@H_404_0@之后访问http://localhost:4200/,查看浏览器的控制台会看到“这个消息是服务器主动推送的”。
@H_404_0@然后点击按钮,查看server项目的控制台会看到“接受到消息:Hello from client”
@H_404_0@现在这种情况是只有在客户端连接的时候服务器才会推送消息,如何在任何需要的时候推送消息呢?
@H_404_0@修改auction_server.ts,添加
setInterval(()=>{ if(wsServer.clients){ wsServer.clients.forEach(client=>{ client.send("这是定时推送"); }) } },2000);
@H_404_0@遍历每个客户端,每2秒给每个客户端推送消息