iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 11
0
Modern Web

Nest.js framework 30天初探系列 第 11

Nestjs framework 30天初探:Day11 WebSocket-Gateways

  • 分享至 

  • xImage
  •  

Gateways

https://ithelp.ithome.com.tw/upload/images/20171214/20107195IrW5KFxpTa.png

Gateway是一個帶有@WebSocketGateway()裝飾器的class,在day01提到的Socket.IO,Nestjs將其做了些封裝,我們只需要使用@WebSocketGateway()的API,就能操作Socket.IO與Client端做互動,整體操作上也蠻簡單明瞭。後續關於Nestjs的WebSocket介紹,其實核心都環繞在Nestjs的主要幾個API,所以後面的介紹會比較像在複習,為了增加點樂趣,我們先讓Nestjs有畫面。

1.安裝ejs模組,然後請在src資料夾底下創建views、assets資料夾(仿expressjs專案)。
cmd指令:

npm install ejs --save & cd src & mkdir views assets
  1. 修改server.ts檔案,來讓Nestjs專案有畫面
    src/server.ts
import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './modules/app.module';
import { INestApplication } from '@nestjs/common/interfaces/nest-application.interface';
import * as express from 'express';//使用express模組
import * as path from 'path';

//創建express 實例
const instance = express();

// view使用ejs範本引擎
instance.set('views', path.join(__dirname, 'views'));
instance.set('view engine', 'ejs');

//NestFactory.create()接受一個模組引數,和一個可選的express實例引數,並返回Promise。
const app: Promise<INestApplication> = NestFactory.create(ApplicationModule, instance);

app
  //Promise傳入nest的實例引數。
  .then(nestInstance =>
    //nest實例具有listen方法,傳入port引數,和一個可選的callback function。
    nestInstance.listen(3000, () => {
      console.log('Application based on Express is listening on port 3000');
    })
  )
  .catch((err) => {
    console.error('Application configured to listen on port 3000 failed to start', err);
  });
  1. 在modules新增Chat資料夾,並在Chat資料夾新增chat.controller.ts和chat.module.ts,程式碼分別如下。
    src/modules/Chat/chat.controller.ts
import { Controller, Get, Request, Response, Next } from '@nestjs/common';

@Controller()
export class ChatController {

    constructor() { }

    @Get('chat')
    //使用Express的參數
    async chat( @Request() req, @Response() res, @Next() next) {
        //跟expressjs專案一樣,指定view路徑,後面帶變數可以直接render到view上
        res.render('./Chat/chat',{title:"聊天室"});
    }
}

src/modules/Chat/chat.module.ts

import { Module } from '@nestjs/common';
import { ChatController } from './chat.controller';
@Module({
    //傳入ChatController
    controllers: [ChatController]
})
export class ChatModule { }
  1. 修改一下app.module.ts,將ChatModule加入modules。
    src/modules/app.module.ts
    部分程式碼
@Module({
  modules: [UsersModule,ChatModule]
})
  1. 在views資料夾底下新增Chat資料夾,並在裏頭新增chat.ejs。
    src/views/Chat/chat.ejs
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>聊天囉</title>
</head>
<body>
    <%= title %>
</body>
</html>

<%= title %>會接受來自ChatController裏頭chat()render過來的title值。

  1. 來實際run一下網頁,下完cmd指令,開啟http://localhost:3000/chat。
    cmd指令
npm start

網頁畫面如下
https://ithelp.ithome.com.tw/upload/images/20171214/20107195TjdgflTIEj.png

Nestjs不愧是base on Expressjs的框架,工程師可以用過往最熟悉的express render方式開發一個網站,不過我還是比較喜歡前後端分離的開發方式拉XDDD。

  1. 今天先建立好server跟client連線就好,在Chat資料夾底下新增 chat.gateway.ts。
    src/modules/Chat/chat.dateway.ts
import { WebSocketGateway, SubscribeMessage, WsResponse, WebSocketServer, WsException } from '@nestjs/websockets';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/map';

//WebSocket listen  port 81
@WebSocketGateway(81)
export class ChatGateway {
    @WebSocketServer() server;

    //訂閱事件名稱
    @SubscribeMessage('wannaChat')
    onEvent(client, message): WsResponse<string> {
        //要聽的事件
        const event = 'wannaChat';
        //接收來自client端傳過來的訊息。
        console.log(message);
        //準備一段回應client端的訊息。
        const response = `Hi,I'm Chat Server.`;
        /*WsResponse的interface結構
        export interface WsResponse<T> {
            event: string;
            data: T;
        }
        */
        //直接推向指定的event,data的值則是我們要推的訊息。
        //這樣做法,有點像是http post完後給一個response。
        return { event, data: response };
    }
}
  1. 修改一下ChatModule,程式碼如下。
    src/modules/Chat/chat.module.ts
import { Module } from '@nestjs/common';
import { ChatController } from './chat.controller';
import { ChatGateway } from './chat.gateway';
@Module({
    //傳入ChatController
    controllers: [ChatController],
    //傳入ChatGateway
    components:[ChatGateway]
})
export class ChatModule { }
  1. 修改一下chat.ejs,程式碼如下。
    src/views/Chat/chat.ejs
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>

    <title>聊天囉</title>
</head>
<body>
    <%= title %>
    <script>    
        const socket = io('ws://localhost:81');
            socket.on('connect', function() {
                console.log('Connected');
                //推一個訊息到wannaChat事件。
                socket.emit('wannaChat', { data: "I'm from browser." });
            });
            socket.on('wannaChat', function(response) {
                console.log(response);
            });
            socket.on('exception', function(data) {
                console.log('wannaChat', data);
            });
            socket.on('disconnect', function() {
                console.log('Disconnected');
            });
    </script>
</body>
</html>
  1. 重啟一下server,瀏覽器打開http://localhost:3000/chat 並看一下瀏覽器console畫面、nestjs console畫面。結果如下。
    瀏覽器畫面
    https://ithelp.ithome.com.tw/upload/images/20171214/20107195C7GobqA1l8.png
    console畫面
    https://ithelp.ithome.com.tw/upload/images/20171214/20107195h4rI05fvn2.png

server 接收到來自client端傳的訊息後,回傳訊息給client端,明天來土炮一個真正的聊天室,今天到這。

程式碼都在github


上一篇
Nestjs framework 30天初探:Day10 Unit Test & E2E Test
下一篇
Nestjs framework 30天初探:Day12 WebSocket-Socket.IO聊天室
系列文
Nest.js framework 30天初探30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言