2017-07-29 23 views
0

我想創建使用PostgreSQL數據庫的Django後端和Angular 4前端之間的實時聊天。假設我想創建chatbot,例如A.L.I.C.E。我不確定,但在我看來,最優化的解決方案是使用websockets?我想在前端寫消息,按回車鍵並將消息發送到後端。然後我想獲得迴應。我正在嘗試以下面顯示的方式執行此操作,但是出現錯誤。我想在前端輸入我自己的文本,按回車併發送。我怎樣才能發送我的消息使用websockets到後端

app.component.html:

<button (click)="sendMsg()">Send Message</button> 

<h4>Type away! Press [enter] when done.</h4> 
<div><key-up3 (keyup7)="send($event)"></key-up3></div> 

app.component.ts:

import { Component } from '@angular/core'; 
import { WebsocketService } from './websocket.service'; 
import { ChatService } from './chat.service'; 
import { Output, EventEmitter } from '@angular/core'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'], 
    providers: [ WebsocketService, ChatService ] 
}) 
export class AppComponent { 

    constructor(private chatService: ChatService) { 
     chatService.messages.subscribe(msg => { 
     console.log("Response from websocket: " + msg); 
     }); 
    } 

    private message = { 
     message: 'this is a test message' 
    } 

    sendMsg() { 
     console.log('new message from client to websocket: ', this.message); 
     this.chatService.messages.next(this.message); 
     this.message.message = ''; 
    } 

    send(msg) { 
    this.message = msg; 
    this.sendMsg(); 
    } 

} 

@Component({ 
    selector: 'key-up3', 
    template: ` 
    <input #box (keyup.enter)="keyup7.emit(box.value)"> 
    <p>{{value}}</p> 
    ` 
}) 
export class KeyUpComponent_v3 { 
    @Output() keyup7 = new EventEmitter<string>(); 
} 

websocket.service.ts:

import { Injectable } from '@angular/core'; 
import * as Rx from 'rxjs/Rx'; 

@Injectable() 
export class WebsocketService { 
    constructor() { } 

    private subject: Rx.Subject<MessageEvent>; 

    public connect(url): Rx.Subject<MessageEvent> { 
    if (!this.subject) { 
     this.subject = this.create(url); 
     console.log("Successfully connected: " + url); 
    } 
    return this.subject; 
    } 

    private create(url): Rx.Subject<MessageEvent> { 
    let ws = new WebSocket(url); 

    let observable = Rx.Observable.create(
    (obs: Rx.Observer<MessageEvent>) => { 
     ws.onmessage = obs.next.bind(obs); 
     ws.onerror = obs.error.bind(obs); 
     ws.onclose = obs.complete.bind(obs); 
     return ws.close.bind(ws); 
    }) 
let observer = { 
     next: (data: Object) => { 
      if (ws.readyState === WebSocket.OPEN) { 
       ws.send(JSON.stringify(data)); 
      } 
     } 
    } 
    return Rx.Subject.create(observer, observable); 
    } 

} 

chat.service.ts:

import { Injectable } from '@angular/core'; 
import { Observable, Subject } from 'rxjs/Rx'; 
import { WebsocketService } from './websocket.service'; 

const CHAT_URL = 'ws://localhost:8000/'; 

export interface Message { 
    message: string 
} 

@Injectable() 
export class ChatService { 
    public messages: Subject<Message>; 

    constructor(wsService: WebsocketService) { 
     this.messages = <Subject<Message>>wsService 
      .connect(CHAT_URL) 
      .map((response: MessageEvent): Message => { 
       let data = JSON.parse(response.data); 
       return { 
        message: data.message 
       } 
      }); 
    } 
} 

UPDATE 模板中的KeyUp.emit(box.value)具有upercase K.在組件中是小寫。但是在這個時候,當我寫東西並按下輸入時,什麼都不會發生。有什麼建議麼?更新後

錯誤: enter image description here

回答

0

你可以一個EventEmitter添加到您的使用keyUp組件

import { Component, Output, EventEmitter } from '@angular/core'; 

@Component({ 
    selector: 'key-up3', 
    template: ` 
    <input #box (keyup.enter)="keyUp.emit(box.value)"> 
    <p>{{value}}</p> 
    ` 
}) 
export class KeyUpComponent_v3 { 
    @Output() keyUp = new EventEmitter<string>(); 
} 

然後在主要成分監聽該事件,並設置消息值accordingly.You將要使您的message屬性公開,以便可以設置模板。

<h4>Type away! Press [enter] when done.</h4> 
<div><key-up3 (keyUp)="message = $event"></key-up3></div> 

此外:

RxJS有一個叫WebSocketSubject類,你可以用它來從服務器發送和接收消息很容易,這裏是一個服務的一個簡單的例子。

import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Rx'; 

@Injectable() 
export class SocketServer { 

    private webSocket$ = Observable.webSocket('ws://localhost:3000/'); 

    public asObservable(): Observable<any> { 
     return this.webSocket$.retry(); 
    } 

    public sendData(value) { 
     this.webSocket$.next(value); 
    } 
} 

.retry()會嘗試,如果它產生斷線

+0

你能告訴我爲什麼你的路比我好重新連接到WebSocket的? – wahtdbogh

+0

我覺得它更簡潔。這將使得從長遠來看更容易維護。我希望有所幫助。 – theOriginalJosh

+0

好的,但是我怎樣才能在前端編寫文本,按回車並將其發送到後端? – wahtdbogh