I have a chat application with SignalR in Net5 and #microsoft/signalr in Angular12. The problem I have is when the connection is lost, i need to reconnect and rejoin a group, the reconnection does work but the reconnection to a group does not.
The function I use to join a group in signalr.service.ts is:
addTogroup(room: any,user:any)
The method I use to recover the connection in signalr.service.ts is:
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.elapsedMilliseconds < 60000) {
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
return Math.random() * 10000;
} else {
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
}
})
Is it possible to access in any way the function that joins you to a group, when the withAutomaticReconnect is being executed? To join the group you need the user and the room that are in app.component.ts
Thank you very much for the help, I have already read the documentation many times but I cannot find the solution.
My code is:
app.component.ts
import { Component, OnInit, ViewChild } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { SignalrService } from '../services/signalr.service';
import { HttpClient } from '#angular/common/http';
import { i18nMetaToJSDoc } from '#angular/compiler/src/render3/view/i18n/meta';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
#ViewChild('myinputfile') myinputfile: any;
title = 'chat-ui';
listMessages: any[] = [];
messages: string[] = [];
message: string = "";
user: string = "";
ticket: string = "";
currentFiles: any = [];
myimg: any = "";
constructor(public signalrService: SignalrService, private http: HttpClient) {
}
ngOnInit(): void {
this.signalrService.startConnection((message: any) => {
this.listMessages.push({ mensaje: message.mensaje, user: message.user, tipo: "texto" });
}, (imageMessage: any) => {
this.listMessages.push(imageMessage);
}, (incomingConnection: any) => {
console.log(incomingConnection);
}, (error:any) => {
console.log(error);
});
}
addRoom() {
this.signalrService.addTogroup(this.ticket, this.user);
}
async sendMessage() {
if (this.myinputfile.nativeElement.files.length > 0) {
let formData = new FormData();
formData.append("RoomId", this.ticket);
formData.append("IdUsuario", this.user);
formData.append("IdCliente", "1");
formData.append("Interno", "1");
formData.append("File", this.myinputfile.nativeElement.files[0]);
await this.signalrService.sendImagesMessage(formData, (response: any) => {
this.myimg = response;
}, (error: any) => {
console.log(error);
});
this.myinputfile.nativeElement.value = "";
} else {
this.signalrService.sendMessageGroup(this.ticket, this.user, this.message);
}
}
onaddremoveFiles() {
if (this.myinputfile.nativeElement.files.length == 0) {
this.myinputfile.nativeElement.click();
} else {
this.myinputfile.nativeElement.value = "";
}
}
onfilesSelected(files: any) { return files.length > 0; }
openImages(src: any) {
let data = src;
let w = window.open('about:blank');
let image = new Image();
image.src = data;
if (w !== null) {
w.document.write(image.outerHTML);
}
}
}
signalr.service.ts
import { Injectable } from '#angular/core';
import * as signalR from "#microsoft/signalr";
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class SignalrService {
public hubConnection!: signalR.HubConnection;
constructor(private http:HttpClient) {
this.buildConnection();
//this.startConnection();
}
public buildConnection = () => {
this.hubConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Information)
.withUrl("https://localhost:44352/chatHub",{
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
//.withAutomaticReconnect([0,1000,5000,6000,7000,8000,10000,15000])
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.elapsedMilliseconds < 60000) {
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
return Math.random() * 10000;
} else {
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
}
})
.build();
};
public startConnection = (
onMessageCallback:Function,
onMessageImageCallback:Function,
onIncomingConnectionCallback:Function,
onErrorCallback:Function) => {
this.hubConnection
.start()
.then(() => {
console.log("Connection Started...");
this.ListeningConnections();
this.ListeningIncomeMessages(onMessageCallback);
this.ListeningIncomeImagesMessages(onMessageImageCallback);
this.ListeningIncomingConnection(onIncomingConnectionCallback);
this.ListeningError(onErrorCallback);
})
.catch(err => {
/*console.log("Error while starting connection: " + err);
setTimeout(() => {
this.startConnection();
}, 3000);*/
});
};
private ListeningConnections(){
this.hubConnection.on("ReceiveConnID", function (connid) {
console.log("ConnID: " + connid);
});
}
public addTogroup(room: any,user:any){
this.hubConnection.invoke("AddToGroup", room, user);
}
public sendMessageGroup(room: any,user:any,message:any){
this.hubConnection.invoke("SendMessageGroup",room, user,message,0)
.catch(function (err) {
return console.error(err.toString());
});
}
public ListeningIncomeMessages(onMessageCallback:Function){
this.hubConnection.on("ReceiveMessageGroup", (user, message) => {
onMessageCallback({mensaje: message, user: user});
});
}
public ListeningIncomingConnection(onIncomingConnectionCallback:Function){
this.hubConnection.on("IncomingConnection",(message) => {
onIncomingConnectionCallback({mensaje: message});
});
}
public ListeningUserConnected(onMessageCallback:Function){
this.hubConnection.on("ReceiveMessageUserConnected", (user, message) => {
onMessageCallback({mensaje: message, user: user});
});
}
public ListeningError(onErrorCallback:Function){
this.hubConnection.on("onError", (message) => {
onErrorCallback({mensaje: message});
});
}
public ListeningIncomeImagesMessages(onImageMessageCallback:Function){
this.hubConnection.on("ReceiveImageMessageGroup", (user, image) => {
//console.log(image);
// console.log(image.idUsuario);
// console.log(image.idCliente);
onImageMessageCallback({ mensaje: image, user: user, tipo: "imagen" });
});
}
public async sendImagesMessage(formData:FormData,onOkCallback:Function,onErroCallback:Function){
await this.http.post("https://localhost:44352/UploadImages",formData).toPromise().then((response)=>{
onOkCallback(response);
}).catch((error)=>{
onErroCallback(error);
console.log(error);
});
}
}
ChatHub.cs
public class ChatHub : Hub
{
public readonly static List<UserViewModel> _Connections = new List<UserViewModel>();
public readonly static List<RoomViewModel> _Rooms = new List<RoomViewModel>();
private readonly static Dictionary<string, string> _ConnectionsMap = new Dictionary<string, string>();
private readonly DbContext _context;
private readonly IMapper _mapper;
private readonly IMensajeService _mensajeService;
private readonly IUnitOfWork _unitOfWork;
public ChatHub(TicketingContext context, IUnitOfWork unitOfWork, IMensajeService mensajeService, IMapper mapper)
{
_context = context;
_mensajeService = mensajeService;
_unitOfWork = unitOfWork;
_mapper = mapper;
}
public IEnumerable<RoomViewModel> GetRooms()
{
if (_Rooms.Count == 0)
{
foreach (var room in _context.Tickets)
{
var roomViewModel = _mapper.Map<Tickets, RoomViewModel>(room);
_Rooms.Add(roomViewModel);
}
}
return _Rooms.ToList();
}
public IEnumerable<UserViewModel> GetUsers(string roomName)
{
return _Connections.Where(u => u.CurrentRoom == roomName).ToList();
}
//envia mensajes a un grupo determinado
public async Task SendMessageGroup(string room, string user, string message, int interno)
{
try
{
var msg = new MensajeGrabarDto()
{
IdTicket = Int32.Parse(room),
IdUsuario = Int32.Parse(user),
Texto = Regex.Replace(message, #"(?i)<(?!img|a|/a|/img).*?>", string.Empty),
Interno = interno,
Adjunto = new byte[] { },
AdjuntoNombre = "",
AdjuntoTipo = ""
//llenar los campos
};
DbResponse respon = await _unitOfWork.MensajeRepository.InsertarMensajeRepository(msg);
if (respon.retcode == 0)
{
await _unitOfWork.SaveChangesAsync();
var mensaje = await _mensajeService.ObtenerMensajesPorTicketService(Int32.Parse(room));
var mensaje2 = mensaje.Where(x => x.IdTicket == Int32.Parse(room)).OrderByDescending(x => x.IdMensaje).FirstOrDefault();
await Clients.Group(room).SendAsync("ReceiveMessageGroup", user, mensaje2);
}
else {
await Clients.Caller.SendAsync("onError", respon.mensaje);
}
}
catch (Exception)
{
await Clients.Caller.SendAsync("onError", "Message not send! Message should be 1-1500 characters.");
}
}
//une a un usuario a determinado grupo
public async Task AddToGroup(string room, string usuario)
{
try
{
await Groups.AddToGroupAsync(Context.ConnectionId, room);
//mensaje para decir que alguien se conecto
await Clients.Group(room).SendAsync("IncomingConnection", $"Alguien se conecto { usuario}");
}
catch (Exception ex)
{
await Clients.Caller.SendAsync("onError", "You failed to join the chat room!" + ex.Message);
}
}
//desloguea a un usuario de un grupo
public async Task Leave(string roomName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
}
public override Task OnConnectedAsync()
{
try
{
Clients.Client(Context.ConnectionId).SendAsync("ReceiveConnID", Context.User.Identity.Name);
}
catch (Exception ex)
{
Clients.Caller.SendAsync("onError", "OnConnected:" + ex.Message);
}
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
try
{
}
catch (Exception ex)
{
Clients.Caller.SendAsync("onError", "OnDisconnected: " + ex.Message);
}
return base.OnDisconnectedAsync(exception);
}
}
Related
Always when I try to join a Group Channel, I am presented with this error
code: 800101
message: "Connection should be made first."
name: "SendBirdException"
Here is my code for connecting to Group Channel.
I am connecting to the SendBird with connect in another function async, and only then calling the connectToChat
The group is created by another user, and this is the code for when a user tries to join that group.
User Connection works fine.
Group retrieval works fine.
But when I try to connect to the group, it errors out.
public connectToChat(chatId: string) {
return new Promise((s, e) => {
const sendBirdEngine = SendBird.getInstance();
try {
if (ChatService.isReady) {
this.log("Connecting to chat...", chatId);
sendBirdEngine.GroupChannel.getChannel(
chatId,
(groupChannel, error) => {
if (error) {
this.logError(
"An error occured while getting channel",
chatId,
error
);
return;
}
this.log("Got the channel!", chatId, groupChannel);
if (groupChannel.isPublic) {
groupChannel.join((response, err) => {
this.log(
"groupChannel Join",
response
// Always getting error here
);
if (err) {
this.logError("connectToChat", err);
e(false);
return;
} else {
s(true);
this.log("Joined the Chat!", chatId);
}
ChatService.chatRooms[
chatId
] = groupChannel;
this.log(
"Successfully Cached the Channel",
chatId
);
});
} else {
this.logError("[ERROR] Channel is Private");
}
// s(true);
}
);
} else {
this.logError("[ERROR] Chat Service is not ready");
}
} catch (err) {
e(err);
}
});
}
EDIT: Added Full Class File for complete reference
class ChatService {
public static userId: string;
public static chatRooms: {
[index: string]: SendBird.BaseChannel;
} = {};
private static isReady: boolean = false;
constructor(userId ? : string) {
if (userId && !ChatService.userId) {
ChatService.userId = userId;
} else {
this.log("userId already set", ChatService.userId);
}
}
/**
* create
*/
public create() {
return new Promise((s, e) => {
if (!ChatService.isReady) {
// connecting to sendbird here
const sendBirdEngine = new SendBird({
appId: "XXXXX-XXXXXX-XXXXXX",
});
this.log("Engine Initialised!", sendBirdEngine);
// init the user
this.initialiseUser((data: any) => {
s(data);
});
}
});
}
/**
* initialise
*/
public async initialiseUser(onReadyHandler: any) {
const userId = ChatService.userId;
this.log("Starting ChatService", userId);
try {
this.connectUserToEngine((res: any) => {
this.log("connectUser() callback", res);
ChatService.isReady = true;
// this.getListOfChatRooms();
onReadyHandler(true);
});
} catch (err) {
onReadyHandler(false);
this.log("[ChatService Error]", err);
}
}
/**
* connects user to engine
*/
public connectUserToEngine(callback: any) {
const sendBirdEngine = SendBird.getInstance();
const userId = ChatService.userId;
this.log("Connecting user...", userId);
sendBirdEngine.connect(userId, (user: any, error: any) => {
if (error) {
this.log("[Error]", error);
this.log("Reconnecting User in 5 seconds...");
setTimeout(() => {
this.connectUserToEngine(callback);
}, 5000);
return;
} else {
this.log("User Connected", user);
callback(user);
}
});
}
/**
* connect to a particular chat
*/
public connectToChat(chatId: string, onNewMessageListener: any) {
return new Promise((s, e) => {
const sendBirdEngine = SendBird.getInstance();
this.log("Current User", sendBirdEngine.currentUser);
try {
if (ChatService.isReady) {
this.log("Connecting to chat...", chatId);
// this.connectUserToEngine(() => {
sendBirdEngine.GroupChannel.getChannel(
chatId,
(groupChannel, error) => {
if (error) {
this.logError(
"An error occured while getting channel",
chatId,
error
);
return;
}
this.log("Got the channel!", chatId, groupChannel);
if (groupChannel.isPublic) {
groupChannel.join((response, err) => {
this.log(
"groupChannel Join",
response
// err
);
// FIXME: Assuming it always works
if (err) {
this.logError("connectToChat", err);
e(false);
return;
} else {
s(true);
this.log("Joined the Chat!", chatId);
}
ChatService.chatRooms[
chatId
] = groupChannel;
this.log(
"Successfully Cached the Channel",
chatId
);
});
} else {
this.logError("[ERROR] Channel is Private");
}
// s(true);
}
);
// });
} else {
this.logError("[ERROR] Chat Service is not ready");
}
} catch (err) {
e(err);
}
});
}
/**
* connects to all chat rooms
*/
public async connectToAllChatRooms(
chatRooms: string[],
onNewMessageListener: any
) {
try {
this.log("connectToAllChatRooms()", chatRooms);
// connect to all chat rooms
for (const chatRoom of chatRooms) {
const x = await this.connectToChat(
chatRoom,
onNewMessageListener
);
}
this.log("connectToAllChatRooms() done");
return true;
} catch (err) {
this.logError("connectToAllChatRooms", err);
throw new Error(err);
}
}
export default ChatService;
I took a look at your code. You ChatService class might need a little change.
Idea 1
On the ChatService class you have a create() method that is not returning a promise, if a user already exists.
public create() {
return new Promise((s, e) => {
if (!ChatService.isReady) {
// connecting to sendbird here
const sendBirdEngine = new SendBird({
appId: "APP_ID"
});
this.log("Engine Initialised!", sendBirdEngine);
// init the user
this.initialiseUser((data: any) => {
s(data);
});
} else {
// Resolve promise when user already exists
s("Already Connected!");
}
});
}
From there it seems to work as expected. Correct me if I'm wrong but this is how I implement your class.
const initChat = () => {
const url = "CHANNEL_URL";
const chat = new ChatService("USER_ID");
chat.create().then(res => {
chat.connectToChat(url).then((res)=>{
console.log("DONE", res)
})
});
};
Idea 2
Also: Perhaps check to see if you are calling
sendBirdEngine.GroupChannel.getChannel()
Before the connection to the user has completed.
Example
Here is a working example of your code if needed. It needs:
index.js - CHANNEL_URL and USER_ID
ChatService.ts - APP_ID
I have a login system with signin with google and facebook option.
after login with facebook, I am able to render the form of a perticular user while after login with google, I am not able to render the complete form of the user and strange thing is the pages get mixed up with each other as showing
below.
while when I am logging in with facebook, it is behaving correctly below.
In both the cases,my logic is same. i.e., I am comparing id and then adding the id to the route. and then on the other component constructor, I am fetching the id from route and then populating the data. below my code snippet.
declare const gapi: any;
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements AfterViewInit {
email = new FormControl('', [Validators.required, Validators.email]);
credential = {};
public auth2: any;
hide = true;
loading = false;
users = [];
pinId;
userId;
userName: string;
constructor(
private element: ElementRef,
private router: Router,
private fb: FacebookService,
private dataService: DataService
) {
console.log('Initializing Facebook');
console.log('ElementRef: ', this.element);
const initParams: InitParams = {
appId: '559178811099356',
xfbml: true,
version: 'v2.8'
};
fb.init(initParams);
}
ngAfterViewInit() {
console.log('in view init');
this.googleInit();
}
googleInit() {
console.log(document.getElementById('googleBtn'));
gapi.load('auth2', () => {
this.auth2 = gapi.auth2.init({
client_id:
'13892768329-54kr4ssbku48jgctclu9b3o7q1h5k3ei.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile email'
});
this.attachSignin(document.getElementById('googleBtn'));
});
}
public attachSignin(element) {
console.log('attach')
this.auth2.attachClickHandler(
element,
{},
googleUser => {
const profile = googleUser.getBasicProfile();
console.log('Token || ' + googleUser.getAuthResponse().id_token);
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
this.userId = profile.getId();
console.log(this.userId);
this.dataService.getUsers().subscribe(data => {
this.users = data;
console.log(this.users);
this.users.forEach(element => {
console.log(element.ID, this.userId);
if (element.ID === this.userId) {
this.pinId = element.pinId;
console.log(this.pinId);
console.log("55555");
this.router.navigate(["schedule/" + this.pinId]);
}
});
}, error => {
console.log('error');
});
},
error => {
alert(JSON.stringify(error, undefined, 2));
}
);
}
getErrorMessage() {
return this.email.hasError('required')
? 'You must enter a value'
: this.email.hasError('email') ? 'Not a valid email' : '';
}
loginWithFb() {
this.fb
.login()
.then((res: LoginResponse) => {
console.log('Logged in', res);
this.userId = res.authResponse.userID;
console.log(this.userId);
this.dataService.getUsers().subscribe(
data => {
this.users = data;
console.log(this.users);
this.users.forEach(element => {
console.log(element.userId, this.userId);
if (element.userId === this.userId) {
this.pinId = element.pinId;
console.log(this.pinId);
console.log('55555');
this.router.navigate(['schedule/' + this.pinId]);
}
});
},
error => {
console.log('error');
}
);
})
.catch(this.handleError);
}
private handleError(error) {
console.error('Error processing action', error);
}
login() {
this.loading = true;
console.log(this.credential);
if (
(this.credential['userName'] === 'shekhar#hummingwave.com' &&
this.credential['password'] === 'shekhar') ||
(this.credential['userName'] === 'ramola#hummingwave.com' &&
this.credential['password'] === 'ramola') ||
(this.credential['userName'] === 'varun#hummingwave.com' &&
this.credential['password'] === 'varun')
) {
console.log('login successfull');
this.dataService.getUsers().subscribe(
data => {
this.users = data;
console.log(this.users);
this.users.forEach(element => {
console.log(element.userName, this.credential['userName']);
if (element.userName === this.credential['userName']) {
this.pinId = element.pinId;
console.log(this.pinId);
console.log('55555');
this.router.navigate(['schedule/' + this.pinId]);
}
});
},
error => {
console.log('error');
}
);
} else if (
this.credential['userName'] === ' ' &&
this.credential['password'] === ' '
) {
console.log('do nothing');
} else {
alert('username and password do not match');
}
}
}
//component where I am populating the form
export class ScheduleComponent implements OnInit {
#ViewChild('f') scheduleForm: NgForm;
selectedTime: '';
selectedDate: '';
confirmation: false;
formData= {};
users = [];
timeOptions = [];
dateOptions = [];
pinId;
hide = true;
credential = {};
constructor(
private router: Router,
private route: ActivatedRoute,
private dataService: DataService
) {
this.route.params.subscribe(params => {
this.pinId = +params['id'];
console.log(this.pinId);
});
this.dataService.getUsers().subscribe(data => {
this.users = data;
console.log(this.users);
this.users.forEach(element => {
console.log(element);
if (element.pinId === this.pinId) {
this.timeOptions = element.timeOptions;
this.dateOptions = element.dateOptions;
console.log(this.timeOptions, this.dateOptions);
}
});
}, error => {
console.log("error");
});
}
onSubmit(form: NgForm) {
this.formData = this.scheduleForm.value;
console.log(this.formData);
this.router.navigate(['confirmation']);
this.router.navigate(["schedule/" + this.pinId + "/confirmation"]);
}
Inside public attachSignin() function, After this.router.navigate(["schedule/" + this.pinId]);
I'm reloading the page again by location.reload();
though it is solving my problem but it is still looking odd as those mixed pages will still come and go in a fraction of a second.
there:
I am want to send some data
here is the code : filename:[wx-resource.ts]
import {Promise} from 'es6-promise';
declare const wx: any;
class WxResource {
public socketOpen: boolean = false;
public count: number = 0;
public socketState;
public reqObj: any = {
url: 'http://192.168.8.138/api/v1/user/auth/status',
token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODcxMjg0MjcsImxldmVsIjoiIiwidWlkIjoiZTE3MmQ0NGUtZGY5Ni00NzBjLTlmM2QtMWJkN2RlNjU3MTA0In0.BG2w-Lo02i2xaga4iZkM7RmP8hXgpRKAC-0MTp5hFj_ugnwATt2m9nDjtmJfRpWnAlpfmXZLgEQTlMHwG2H9hhoqojJC6piCh76UkH0mNwjJrBGiTINurholwTF2VYQPysB4bz7G4jepzEccNdD_NW-_Rxw-Bo5WDcH37OZ2zTw"
};
constructor() {
this.listen().connect().afterConnect();
}
private listen(): WxResource {
let _that = this;
wx.onSocketOpen((event) => {
console.info('WebSocket已打开:', event);
this.count++;
this.socketState = event.target.readyState;
this.socketOpen = true;
// this.sendMsg(_that.reqObj,"GET");
console.log("open的次数:", this.count);
return this.socketOpen;
});
wx.onSocketError((event) => {
console.error('WebSocket连接打开失败,请检查!', event);
});
// console.log("外部:", this.socketOpen);
return this;
}
private connect(): WxResource {
wx.connectSocket({
url: "ws://192.168.8.138/api/ws"
});
return this;
}
private afterConnect(resolve?, reject?): WxResource {
wx.onSocketMessage((res) => {
console.log("服务器返回:", JSON.parse(res.data));
resolve(JSON.parse(res.data));
});
return this;
}
//发送消息
private sendMsg(reqObj, method?) {
console.log("socketState: ", this.socketState); //undefined
if (!this.socketOpen) {
console.log("webSocket opened");
// 判断是否传入token
let header = {};
if (reqObj.token === undefined) {
console.log("no token");
header = {
"S-Request-Id": Date.now() + Math.random().toString(20).substr(2, 6)
}
} else if (reqObj.token !== undefined) {
console.log("get token");
header = {
"S-Request-Id": Date.now() + Math.random().toString(20).substr(2, 6),
"Authentication": "Bearer " + reqObj.token
}
}
wx.sendSocketMessage({
data: JSON.stringify({
"method": method,
"url": reqObj.url,
"header": header,
"body": JSON.stringify(reqObj.data)
}),
success: function (res) {
console.log("发送成功", res)
},
fail: function (res) {
console.log("发送失败", res)
}
});
} else {
console.log("socket not open", this.socketOpen);
}
}
public get() {
let _that = this;
console.log("socketOpen", this.socketOpen);
this.sendMsg(this.reqObj, "GET");
return new Promise((resolve, reject) => {
_that.afterConnect(resolve, reject);
})
}
}
export default WxResource;
then I'm import above code like this:
import WxResource from '../../utils/wx-resource'
and use it
const wxResource = new WxResource();
wxResource.get();
and something went wrong:
here is the console:
"sendSocketMessage:fail Failed to execute 'send' on 'WebSocket': Still in CONNECTING state."
I just want to call wx.onSocketOpen (), and then by calling the get method when using wx.sendSocketMessage to send data to the server,method POST, DELETE the same, without calling wx.onSocketOpen () again; I don't know where is wrong, please point out, thank you
I did not manage to remove a deleted item from screen.
New or updated items are reflected in screen, but I don't know what to do to reflect deleted ones.
I even created a separated list (using methods findIndex, emit) and splice the element from that list but it didn't work as well.
My provider:
export class AssetTypeService {
private assettypes$: any;
private assettypesRef: any;
private assettypeslist: AssetType[] = [];
constructor(private http: Http) {
this.assettypesRef = firebase.database().ref('asset-type');
this.assettypesRef.on('child_added', this.handleDataChildAdded, this);
this.assettypesRef.on('child_changed', this.handleDataChildAdded, this);
this.assettypesRef.on('child_removed', this.handleDataChildRemoved, this);
this.assettypes$ = new ReplaySubject();
}
get getAssetTypes() {
return this.assettypes$;
}
handleDataChildAdded(snap) {
try {
let type: AssetType = <AssetType>{};
type.id = snap.key;
type.description = snap.val().description;
this.assettypes$.next(type);
} catch (error) {
console.log('catching', error);
}
}
handleDataChildRemoved(snap) {
try {
let index: number = this.findIndex(snap.key);
if (index !== -1) {
this.assettypeslist.splice(index, 1);
this.emit();
}
} catch (error) {
console.log('catching', error);
}
}
private findIndex(key: string): number {
return this.assettypeslist.findIndex((assetType: AssetType) => {
return assetType.id === key;
});
}
private emit(): void {
this.assettypes$.next(this.assettypeslist);
}
saveAssetType(assetType: AssetType) {
if (assetType.id == undefined) {
assetType.id = firebase.database().ref().child('asset-type').push().key;
}
var updates = {};
updates['/asset-type/' + assetType.id] = assetType;
return firebase.database().ref().update(updates);
}
getAssetType(uid: string) {
let assetType: AssetType = <AssetType>{};
return firebase.database().ref('/asset-type/' + uid).once('value').then(function (snapshot) {
assetType = { id: snapshot.key, description: snapshot.val().description };
return assetType;
});
}
deleteAssetType(uid: string) {
return firebase.database().ref('asset-type/' + uid).remove();
}
}
My controller:
ngOnInit() {
this.getAssetTypes();
}
getAssetTypes() {
this.assetTypeService.getAssetTypes.subscribe((data) => {
let alreadyExists = false;
this.types.forEach(function (assetType) {
if (assetType.id == data.id) {
alreadyExists = true;
assetType.description = data.description;
}
});
if (!alreadyExists) {
this.types.push(data);
}
}, (err) => {
console.error(err);
console.log(err);
});
}
deleteAssetType(uid: string) {
this.assetTypeService.deleteAssetType(uid).then(data => {
this.showToast('Asset type deleted successfully');
});
}
I am building a chat app. I have a client (Ionic 2) talking to a server (Java). The client can receive messages successfully from the server (e.g. "Welcome to the chat!" is received when connecting), but when I try send a message to the server from the client, it does not get there (the DataListener<Message> is not being invoked on the "chat_message:send" event.).
Please any suggestions?
Server Code:
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
public class Server {
public static void main(String[] args) {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(3700);
final SocketIOServer server = new SocketIOServer(config);
server.addConnectListener(new ConnectListener() {
#Override
public void onConnect(SocketIOClient client) {
System.out.println("onConnected");
client.sendEvent("chat_message:message", new Message("Welcome to the chat!"));
}
});
server.addDisconnectListener(new DisconnectListener() {
#Override
public void onDisconnect(SocketIOClient client) {
System.out.println("onDisconnected");
}
});
server.addEventListener("chat_message:send", Message.class, new DataListener<Message>() {
#Override
public void onData(SocketIOClient client, Message data, AckRequest ackSender) throws Exception {
System.out.println("onSend: " + data.toString());
server.getBroadcastOperations().sendEvent("chat_message:message", data);
}
});
System.out.println("Starting server...");
server.start();
System.out.println("Server started");
}
}
and
public class Message {
private String message;
public Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Client Code:
import { Component, NgZone } from '#angular/core';
import { Http } from "#angular/http";
import { MessageModel } from '../model/messageModel';
import { UtilityService } from '../utils/utilityService';
declare var io;
#Component({
templateUrl: 'build/pages/chat/chat.html',
providers: [UtilityService]
})
export class ChatPage {
private socketHost: string = "http://localhost:3700";
private messages: MessageModel[] = [];
private zone: NgZone = null;
private chatBox: string = null;
private socket: any = null;
private utilityService: UtilityService = null;
constructor(http: Http, utilityService: UtilityService) {
this.utilityService = utilityService;
this.setUpMessageService(http);
}
setUpMessageService(http: Http): void {
this.messages = [];
this.zone = new NgZone({ enableLongStackTrace: false });
let url = this.socketHost + "/fetch";
http.get(url).subscribe((success) => {
var data = success.json();
console.log(data);
for (var i = 0; i < data.length; i++) {
this.messages.push(data[i].message);
}
}, (error) => {
console.log(JSON.stringify(error));
});
this.chatBox = "";
this.socket = io(this.socketHost);
this.socket.on("chat_message:message", (messageModel: MessageModel) => {
this.zone.run(() => {
console.log('run: ' + messageModel);
this.messages.push(messageModel);
});
});
}
send(msg) {
if (msg && msg != "") {
let messageModel: MessageModel = new MessageModel();
messageModel.message = msg;
console.log(messageModel);
this.socket.emit("chat_message:send", messageModel);
}
this.chatBox = "";
}
}
and
import { Injectable } from "#angular/core";
#Injectable()
export class MessageModel {
public message: string = null;
}
If I send the message as a String and not a MessageModel from the client it works.