angular - WebSocket kunde inte ansluta
Jag försöker göra en funktion för delning av liveplats för min app, men jag har några problem med SignalR-delen.
Bara en kort beskrivning av vad jag försöker göra här: Denna hubb ska bara skicka till de personer som delar sin plats live. Först försöker jag upprätta en anslutning för sändaren och när startknappen trycks börjar anslutningen, men den fortsätter att stå i "Ansluter"-läge och meddelandet om en ny användare som ska skicka sin plats registreras inte, och jag undrar vad jag gjorde fel. Jag följde en handledning för en chatt och försökte anpassa den efter mina behov, men förmodligen behöver något läggas till eller redigeras för att det ska fungera som jag vill.
share-live.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { take } from 'rxjs/operators';
import { MapService } from 'src/app/services/location/map.service';
import { AccountService } from 'src/app/shared/services';
import { ShareLiveService } from '../services/share-live.service';
@Component({
selector: 'app-share-live',
templateUrl: './share-live.component.html',
styleUrls: ['./share-live.component.scss']
})
export class ShareLiveComponent implements OnDestroy{
userPosition: google.maps.LatLngLiteral = null;
username: string;
stopWatch = true;
connectedToHub = false;
isSharing = new BehaviorSubject<boolean>(false);
id: number;
options: google.maps.MapOptions = {
center: {lat: 45.9432, lng: 26.5},
zoom: 16
};
markerOptions: google.maps.MarkerOptions = {
clickable: true,
draggable: false,
};
markerSettings = [
{
visible:true,
shape:'Circle',
fill:'white',
width:3,
animationDuration:0,
border:{width:2,color:'#333'}
}
];
constructor(
readonly mapService: MapService,
private readonly shareLiveService: ShareLiveService,
private readonly accountService: AccountService
) {
this.accountService.currentUserSource
.pipe(take(1))
.subscribe(user => this.username = user.username);
this.positionMap();
}
ngOnDestroy(): void {
if(this.connectedToHub){
this.stopHubConnection();
}
}
start(): void {
this.stopWatch = false;
this.isSharing.next(!this.stopWatch);
this.connectDisconectHub();
this.id = navigator.geolocation.watchPosition((position) => {
console.log(position);
this.refreshOptions(position.coords);
this.refreshLocation(position.coords);
});
}
stop(): void {
this.stopWatch = true;
this.connectDisconectHub();
if(this.id){
navigator.geolocation.clearWatch(this.id);
this.id = null;
this.isSharing.next(!this.stopWatch);
}
}
private connectDisconectHub(): void {
if(!this.connectedToHub){
this.createHubConnection();
} else {
this.stopHubConnection();
}
}
private createHubConnection(): void {
this.shareLiveService.createHubConnection(this.username);
this.connectedToHub = true;
}
private stopHubConnection(): void {
this.shareLiveService.eraseSharer(this.username)
.catch(error=> console.log(error));
this.shareLiveService.stopHubConnection();
this.connectedToHub = false;
}
private positionMap(): void {
navigator.geolocation.getCurrentPosition((position) => {
this.refreshOptions(position.coords);
});
}
private refreshOptions(coordinates: GeolocationCoordinates): void {
this.options = {
...this.options,
center: {lat: coordinates.latitude, lng: coordinates.longitude}
};
}
private refreshLocation(coordinates: GeolocationCoordinates): void {
this.userPosition = {lat: coordinates.latitude, lng: coordinates.longitude};
}
}
share-live.service.ts
import { Injectable } from '@angular/core';
import { HttpTransportType, HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
import { BehaviorSubject, Observable } from 'rxjs';
import { LocationCoords } from 'src/app/shared/types';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class ShareLiveService {
hubUrl = environment.hubUrl;
livesharerSource$: Observable<{username: string}[]>;
private hubConnection: HubConnection;
private livesharer = new BehaviorSubject<{username: string}[]>([]);
constructor() {
this.livesharerSource$ = this.livesharer.asObservable();
}
createHubConnection(username: string): void {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.hubUrl + 'locationsharers',{
skipNegotiation: true,
transport: HttpTransportType.WebSockets
})
.build();
this.hubConnection.start()
.then(() => this.sendNewSharer(username))
.catch(error => console.log(error));
}
stopHubConnection(): void {
if(this.hubConnection){
this.hubConnection.stop()
.then(() => console.log('Connection stopped!'))
.catch(error => console.log(error));
}
}
async sendNewSharer(username: string): Promise<any> {
return this.hubConnection.invoke('AddNewSharer', username)
.catch(error => console.log(error));
}
async eraseSharer(username: string): Promise<any> {
return this.hubConnection.invoke('RemoveSharer', username)
.catch(error => console.log(error));
}
}
miljö.ts
export const environment = {
production: false,
url:'https://localhost:5001/api',
hubUrl: 'http://localhost:5001/hubs/',
mapbox: {
accessToken: 'token'
}
};
LiveLocationSharersHub.cs
using DataAccessAPI.DTOs;
using DataAccessAPI.Entities;
using DataAccessAPI.Interfaces;
using Microsoft.AspNetCore.SignalR;
namespace DataAccessAPI.SignalR
{
public class LiveLocationSharersHub : Hub
{
private readonly ILiveLocationSharersRepository _liveLocationSharersRepository;
private readonly ILiveLocationRepository _liveLocationRepository;
public LiveLocationSharersHub(ILiveLocationSharersRepository liveLocationSharersRepository, ILiveLocationRepository liveLocationRepository)
{
_liveLocationSharersRepository = liveLocationSharersRepository;
_liveLocationRepository = liveLocationRepository;
}
public override async Task OnConnectedAsync()
{
var httpContext = Context.GetHttpContext();
await Groups.AddToGroupAsync(Context.ConnectionId, "people-sharing");
var peopleSharing = _liveLocationSharersRepository.GetAll();
await Clients.Group("people-sharing").SendAsync("PeopleSharingLocation", peopleSharing);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
public async Task AddNewSharer(string username)
{
if (!await _liveLocationRepository.UserExistsAsync(username))
{
throw new HubException("This user doesn't exist! Something is wrong.");
}
var newSharer = new LiveLocationSharer
{
Username = username
};
_liveLocationSharersRepository.AddSharer(newSharer);
if (await _liveLocationRepository.SaveAllAsync())
{
await Clients.Group("people-sharing").SendAsync("NewSharer", username);
}
else
{
throw new HubException("Something went wrong.");
}
}
public async Task RemoveSharer(string username)
{
if (!await _liveLocationRepository.UserExistsAsync(username))
{
throw new HubException("This user doesn't exist! Something is wrong.");
}
var sharer = await _liveLocationSharersRepository.GetLiveLocationSharersAsync(username);
_liveLocationSharersRepository.Delete(sharer);
if (await _liveLocationRepository.SaveAllAsync())
{
await Clients.Group("people-sharing").SendAsync("UserDeleted", username);
}
else
{
throw new HubException("Something went wrong.");
}
}
}
}
konfigurationsmetod
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebAPIv5 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:8100"));
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<LiveLocationHub>("hubs/livelocation");
endpoints.MapHub<LiveLocationSharersHub>("hubs/locationsharers");
});
}
Svar #1
Löste problemet, det var faktiskt ett litet problem som kunde lösas med bara lite uppmärksamhet.
i filen enviroments.ts saknades ett 's' i URL:en för hubs, så istället för 'http' är det 'https'
export const environment = {
production: false,
url:'https://localhost:5001/api',
hubUrl: 'https://localhost:5001/hubs/',
mapbox: {
accessToken: 'token'
}
};
