项目简介描述:模拟在在线商品竞拍,单击关注某个商品时,可以在商品详情页上看到实时的看到的别人竞拍的商品价格,模拟从后端实时的获取数据,当
单击取消按钮时,客户端即取消对服务器端的返回的数据的订阅,并关闭数据流。
项目流程图:
项目步骤:
1. 对点击关注按钮进行编码:
1 // 模板代码 2 <div class="thumbnail"> 3 <button class="btn btn-default btn-lg" [class.active]="isWatched" (click)=\'watchProduct()\'> 4 {{isWatched ? \'取消关注\':\'关注\' }} 5 </button> 6 <label>最新出价: {{currentBid | number: \'.2-2\'}}元</label> 7 </div>
2. 模板中的ts属性的添加:
// 关注参数 public isWatched: boolean = false ; // 是否关注,默认是false,即为没有关注某个商品 public currentBid: number; // 当前商品的价格 // 保存这个流 public subscription: Subscription; // 当订阅一个流时的返回值,使用它可以取消对某个流的订阅 // 注入WebsocketService, 支持websocket协议,支持双向的通信,即客户端和服务器能同时回复和发送数据 // 服务需要注入器,此例中的引入的WebsocketService时,可以在constructor快速的实现注入,即可以使用 constructor(private productService: ProductService, private routeInfo: ActivatedRoute, private wsService: WebsocketService) { }
3. 作为中介媒体的服务来成为WebSocket的服务的创建流,发送消息的函数:
// 常见WebSocket对象 public ws: Websocket; // 通过url来创建websocket流, 返回可观测的流 createObservableSocket(url: string, id: number): Observable<any> { 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(); // 当关闭时,可观察对象的完毕 this .ws.onopen = (event) => this .sendMessage({productId: id}); // 当ws打开时,即通过函数sendMessage发送数据 return () => this .ws.close(); // 这个匿名函数取消订阅的方法的时候调用,关闭WebSocket, 否则的话,容易造成内存的泄露; } ) } // 通过创建的ws对象,来发送数据,发送的数据的格式是字符串的格式 sendMessage(message: any) { this .ws.send(JSON.stringify(message)); // 穿过来的参数是对象,但是send消息的格式是字符串格式的; }
4. 在服务器中实现对productId的存储:
const Server = require(\'ws\').Server; // 后端创建ws服务器 // Map中存在的是:每一个客户端关注的商品的id的数组,因为每一个客户端可以关注多个商品; const subscriptions = new Map<any, number[]> (); const wsServer = new Server({port: 8090 }); wsServer.on( \'connection\', (websocket) => { websocket.on( \'message\', (message) => { // 当客户端有信息传递时,即服务器端接收,由于这个客户端传递个是JSON.stringify({productId:id});所以在接到数据时,使用 // JSON.parse(message); let messageObj = JSON.parse(message); // key值是连接到服务端的客户端,当subscripitons.get(websocket)的值为undefined,则赋值为空数组; let productIds = subscriptions.get(websocket) || []; // 将新的商品的Id放到值的数组中;将已有的和新建的id组合在一起; subscriptions.set(websocket, [...productIds, messageObj.productId]); // [...productIds]: 扩展运算符 }) })
1 // 实现消息向客户端的定时的推送 2 // 模拟数据的更新 3 setInterval( function () { 4 // 随机生成每个商品的最新的商品的价格 5 products.forEach((product) => { 6 let currentBid = currentBids.get(product.id) || product.price; 7 let newBid = currentBid + Math.random() * 5 ; 8 currentBids.set(product.id, newBid); 9 }) 10 // 循环每一个客户端, 推送每一个客户端关注的商品的价格 11 subscriptions.forEach((productIds: number[], ws) => { 12 // 返回的数据的格式是:[{productId:xxx,bid: xxx},{},{}],对应是每个被关注的商品的最新的报价 13 // *** 防止页面刷新报错; 14 if (ws.readyState === 1 ) { 15 // 通过映射将pid组成{productId: pid, bid: currentBid.get(pid)} 16 let newBids = productIds.map(pid => ({ 17 productId: pid, 18 bid: currentBids.get(pid) 19 })); 20 // 发送的数据 21 ws.send(JSON.stringify(newBids)); 22 } else { 23 subscriptions. delete (ws); // 删除已经关闭的客户端 24 } 25 // 这之后,然后在客户端订阅这个流; 26 }); 27 }, 2000);
5. 客户端对服务器的流的接收(关注)和取消(取消关注):
1 watchProduct() { 2 // 服务器返回的流的订阅 3 if ( this .subscription) { 4 // 取消对流的订阅, 并对subscription赋值为null; 5 this .subscription.unsubscribe(); 6 this .isWatched = false ; // 按钮的状态的变化 7 this .subscription = null ; // 将流的对象置空 8 } else { 9 this .isWatched = true ; // 按钮的状态的变化 10 this .subscription = this .wsService.createObservableSocket(\'ws://localhost:8090\', this .product.id) 11 .subscribe( 12 products => { 13 products = JSON.parse(products); 14 console.log(products); 15 let product = products.find(p => p.productId == this .product.id); // 通过id筛选出当前的商品 16 this .currentBid = product.bid; // 展示在页面上 17 } 18 ); 19 } 20 }
6. 重点是websocket的编程的流的创建和订阅,node服务器来模拟用户的访问和出价,对流的数据的处理。
对websocket的编程的流程有大概的了解。
查看更多关于angular5 websocket 商品价格 关注商品价格 在线商品竞拍的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did223044