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');
});
}
Related
I'm working with rxdb and I have pull and push handlers for the backend I have used supabase
I have setup the code for replication as follows:
replication.ts
import { RxDatabase } from "rxdb";
import { RxReplicationPullStreamItem } from "rxdb/dist/types/types";
import { replicateRxCollection } from "rxdb/plugins/replication";
import { Subject } from "rxjs";
import { supabaseClient, SUPABASE_URL } from "src/config/supabase";
import { DbTables } from "src/constants/db";
import {
blockPullHandler,
blockPushHandler,
} from "./repilicationhandlers/block";
import { CheckpointType, RxBlockDocument, RxBlocksCollections } from "./types";
export async function startReplication(
database: RxDatabase<RxBlocksCollections>
) {
const pullStream$ = new Subject<
RxReplicationPullStreamItem<RxBlockDocument, CheckpointType>
>();
supabaseClient
.from(DbTables.Block)
.on("*", (payload) => {
console.log("Change received!", payload);
const doc = payload.new;
pullStream$.next({
checkpoint: {
id: doc.id,
updated: doc.updated,
},
documents: [doc] as any,
});
})
.subscribe((status: string) => {
console.log("STATUS changed");
console.dir(status);
if (status === "SUBSCRIBED") {
pullStream$.next("RESYNC");
}
});
const replicationState = await replicateRxCollection({
collection: database.blocks,
replicationIdentifier: "supabase-replication-to-" + SUPABASE_URL,
deletedField: "archived",
pull: {
handler: blockPullHandler as any,
stream$: pullStream$.asObservable(),
batchSize: 10,
},
push: {
batchSize: 1,
handler: blockPushHandler as any,
},
});
replicationState.error$.subscribe((err) => {
console.error("## replicationState.error$:");
console.log(err);
});
return replicationState;
}
blockPullHandler:
export const blockPullHandler = async (
lastCheckpoint: any,
batchSize: number
) => {
const minTimestamp = lastCheckpoint ? lastCheckpoint.updated : 0;
console.log("Pulling data", batchSize, lastCheckpoint);
const { data, error } = await supabaseClient
.from(DbTables.Block)
.select()
.gt("updated", minTimestamp)
.order("updated", { ascending: true })
.limit(batchSize);
if (error) {
console.log(error);
throw error;
}
const docs: Array<Block> = data;
return {
documents: docs,
hasMoreDocuments: false,
checkpoint:
docs.length === 0
? lastCheckpoint
: {
id: lastOfArray(docs).id,
updated: lastOfArray(docs).updated,
},
};
};
blockPushHandler:
export const blockPushHandler = async (
rows: RxReplicationWriteToMasterRow<RxBlockDocumentType>[]
) => {
if (rows.length !== 1) {
throw new Error("# pushHandler(): too many push documents");
}
const row = rows[0];
const oldDoc: any = row.assumedMasterState;
const doc: Block = row.newDocumentState;
console.log(row, oldDoc, doc);
// insert
if (!row.assumedMasterState) {
const { error } = await supabaseClient.from(DbTables.Block).insert([doc]);
console.log("Error 1", error);
if (error) {
// we have an insert conflict
const conflictDocRes: any = await supabaseClient
.from(DbTables.Block)
.select()
.eq("id", doc.id)
.limit(1);
return [conflictDocRes.data[0]];
} else {
return [];
}
}
// update
console.log("pushHandler(): is update");
const { data, error } = await supabaseClient
.from(DbTables.Block)
.update(doc)
.match({
id: doc.id,
replicationRevision: oldDoc.replicationRevision,
});
console.log("Error 2", error);
if (error) {
console.log("pushHandler(): error:");
console.log(error);
console.log(data);
throw error;
}
console.log("update response:");
console.log(data);
if (data.length === 0) {
// we have an updated conflict
const conflictDocRes: any = await supabaseClient
.from(DbTables.Block)
.select()
.eq("id", doc.id)
.limit(1);
return [conflictDocRes.data[0]];
}
return [];
};
But the issue is when I start the application and the pull handler is called correctly but it doesn't stop calling the pull handler and it sends continuous request one after another even after it has fetched the documents even when I set hasMoreDocuments to false It keeps sending requests and running the replicator. Is there something wrong with my configuration?
database.ts:
export const createDatabase = async () => {
const database = await createRxDatabase({
name: "sundaedb",
storage: getRxStorageDexie(),
});
await database.addCollections({
blocks: {
schema: blockSchema as any,
conflictHandler: conflictHandler as any,
},
documents: {
schema: documentSchema as any,
conflictHandler: conflictHandler as any,
},
});
database.blocks.preInsert((docData) => {
docData.replicationRevision = createRevision(
database.hashFunction,
docData as any
);
return docData;
}, false);
database.blocks.preRemove((docData) => {
console.log(" PRE REMOVE !!");
console.log(JSON.stringify(docData, null, 4));
const oldRevHeight = parseRevision(docData.replicationRevision).height;
docData.replicationRevision =
oldRevHeight + 1 + "-" + database.hashFunction(JSON.stringify(docData));
console.log(JSON.stringify(docData, null, 4));
return docData;
}, false);
database.blocks.preSave((docData) => {
const oldRevHeight = parseRevision(docData.replicationRevision).height;
docData.replicationRevision =
oldRevHeight + 1 + "-" + database.hashFunction(JSON.stringify(docData));
return docData;
}, false);
return database;
};
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);
}
}
I have written three files which are: home-flatfull.jsp, settings-social-prefs.html and
google-js-api-wrapper.js files.
In home-flatfull.jsp file, I have written as below:
head.js('jscore/lib/base64.js', 'jscore/lib/google-js-api.js', 'jscore/lib/google-js-api-wrapper.js', function () {
var config = {
apiKey: 'AIzaSyCa52K8J68kr5b4S7Afu1FQzeleCfvzOFs',
clientId: '492662354647-877atvgj1a0pu82nrutsm50rcmg0lufh.apps.googleusercontent.com',
discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"],
scopes: 'https://www.googleapis.com/auth/gmail.readonly',
listener: function(response){
console.log(' Check google ');
console.log(response);
}
};
googleJSAPI = GoogleJSAPI.getInstance(config);
});
In settings-social-prefs.html file I have defined as below:
<a onclick="googleJSAPI.signIn()" class="btn btn-sm btn-default">
{{agile_lng_translate 'prefs-email' 'enable'}}
</a>
In google-js-api-wrapper.js file, I have defined as below:
class GoogleJSAPI {
emailRegx = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
instance;
isActive = false;
constructor(config) {
console.log(' google code loaded ');
gapi.load('client:auth2', () => {
gapi.client.init({
apiKey: config.apiKey,
clientId: config.clientId,
discoveryDocs: config.discoveryDocs,
scope: config.scopes
}).then(() => {
this.isActive = true;
console.log(' config loaded ');
gapi.auth2.getAuthInstance().isSignedIn.listen(config.listener);
}, (error) => {
this.isActive = false;
console.log(JSON.stringify(error, null, 2));
});
});
}
static getInstance(config) {
if (!this.instance) {
this.instance = new GoogleJSAPI(config);
}
return this.instance;
}
isActive() {
return this.isActive;
}
isUserLoggedIn() {
return gapi.auth2.getAuthInstance().isSignedIn.get();
}
signIn = () => {
gapi.auth2.getAuthInstance().signIn();
}
signOut() {
gapi.auth2.getAuthInstance().signOut();
}
getSorted(a, b) {
return new Date(b.date).getTime() - new Date(a.date).getTime();
}
getMailList(queryObject) {
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.list(queryObject).then(function (response) {
resolve(response.result);
});
});
}
getMailContentById(id) {
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.get({
'userId': 'me', 'id': id
}).then((response) => {
let message = {};
let headers = response.result.payload.headers;
headers.forEach((header) => {
if (header.name === "From") {
message['from'] = header.value;
} else if (header.name === "Subject") {
message['subject'] = header.value;
} else if (header.name === "To") {
message['to'] = theader.value;
} else if (header.name === "Date") {
message['date'] = header.value;
} else if (header.name === "Cc") {
message['cc'] = header.value;
}
});
try {
if (response.result.payload) {
let body = "";
if (response.result.payload.body.size > 0) {
body = response.result.payload.body.data;
} else {
let bodyParts = response.result.payload.parts;
bodyParts.forEach((part, index) => {
if (part.type = "text/html") {
//console.log(index);
body = part.body.data;
return;
}
});
}
message['message'] = Base64.decode(body);
// console.log(message['body']);
}
} catch (e) {
//console.log(index);
//console.log(response.result);
//console.log(e);
}
resolve(message);
});
});
}
getInboxMailsWithContent(nextPageToken, fromEmail) {
var qData = '';
var queryObject = {
'userId': 'me',
'labelIds': ['INBOX']
};
if (nextPageToken) {
queryObject['pageToken'] = nextPageToken;
}
if (fromEmail) {
qData += 'from:' + fromEmail;
}
queryObject['q'] = qData;
return new Promise((resolve, reject) => {
gapi.client.gmail.users.messages.list(queryObject).then((response) => {
let resultObject = {
nextPageToken: response.result.nextPageToken
};
let messages = new Array();
let rawMessages = response.result.messages;
rawMessages.forEach((rawMessage, index) => {
gapi.client.gmail.users.messages.get({
'userId': 'me', 'id': rawMessage.id
}).then((response) => {
let message = {
id: rawMessage.id
};
let headers = response.result.payload.headers;
headers.forEach((header) => {
if (header.name === "From") {
message['from'] = header.value;
} else if (header.name === "Subject") {
message['subject'] = header.value;
} else if (header.name === "To") {
message['to'] = header.value;
} else if (header.name === "Date") {
message['date'] = header.value;
} else if (header.name === "Cc") {
message['cc'] = header.value;
}
});
try {
if (response.result.payload) {
let body = "";
if (response.result.payload.body.size > 0) {
body = response.result.payload.body.data;
} else {
let bodyParts = response.result.payload.parts;
bodyParts.forEach((part, index) => {
if (part.type = "text/html") {
f //console.log(index);
body = part.body.data;
return;
}
});
}
message['message'] = Base64.decode(body);
// console.log(message['body']);
}
} catch (e) {
//console.log(index);
//console.log(response.result);
//console.log(e);
}
messages[index] = message;
});
});
// resultObject.messages = messages.sort(this.getSorted);
resultObject.messages = messages;
resolve(resultObject);
});
});
}
}
function getInboxMailsWithContent(nextPageToken, fromEmail, callback) {
googleJSAPI.getInboxMailsWithContent(nextPageToken, fromEmail).then((response) => {
setTimeout(() => {
if (callback && typeof (callback) == "function") {
callback(response);
}
}, 3000);
});
}
When I clicked on enable button in settings-social-prefs.html file, I am just getting the gmail login page and gmail password page once I have provided gmail username and password, I got the consent screen which asks to allow access to user's email then I am getting the blank screen without getting the Gmail Read-Only mails of a specified user who has logged in. Can you please help me on this to get Gmail Read-Only mails when I click on enable button.
you may turn off two factor authentication (if on) and also "allow low secure apps to connect" in google my account settings
Ps: Displaying API in public should be avoided :-)
I have this javascript class in which I have declared two properties and I have problems with the first one. I am trying to handle the tokens with Firebase in a project with node.js and react.js
export default class NoNotificationResource {
allTokens = [];
tokensLoaded = false;
constructor(messaging, database) {
this.database = database;
this.messaging = messaging;
try {
this.messaging.requestPermission().then(res => {
console.log('Permiso concedido');
}).catch(err => {
console.log('no acces', err);
});
} catch (err) {
console.log('NO hay soporte para notificaciones', err);
};
this.setupTokenRefresh();
this.database.ref('/fcmTokens').on('value', snapshot => {
this.allTokens = snapshot.val();
this.tokensLoaded = true;
})
};
setupTokenRefresh(){
this.messaging.onTokenRefresh(() => {
this.saveTokenToServer();
})
};
saveTokenToServer(){
this.messaging.getToken().then(res => {
if (this.tokensLoaded) {
const existingToken = this.findExistingToken(res);
if (existingToken) {
//Reemplazar token
} else {
//Crear nuevo token
}
}
});
}
findExistingToken(tokenToSave){
for(let tokenKey in this.allTokens){
const token = this.allTokens[tokenKey].token;
if (token === tokenToSave) {
return tokenKey;
}
}
return false;
}
}
Without the linter it doesn't show any errors (I modified your code so it doesn't look for services it cannot reach).
The only change is that I moved allTokens into the constructor - more:
Declare a class property outside of a class method
Private properties in JavaScript ES6 classes
I added a "manual" setToken to show that this.allTokens works.
'use strict'; // just to make sure
class NoNotificationResource {
tokensLoaded = false;
constructor(messaging, database) {
this.allTokens = [];
this.database = database;
this.messaging = messaging;
try {
this.messaging.requestPermission().then(res => {
console.log('Permiso concedido');
}).catch(err => {
console.log('no acces', err);
});
} catch (err) {
console.log('NO hay soporte para notificaciones', err);
};
if (this.messaging) {
this.setupTokenRefresh();
this.database.ref('/fcmTokens').on('value', snapshot => {
this.allTokens = snapshot.val();
this.tokensLoaded = true;
})
}
};
setupTokenRefresh() {
if (this.messaging && this.messaging.onTokenRefresh) {
this.messaging.onTokenRefresh(() => {
this.saveTokenToServer();
})
}
};
saveTokenToServer() {
this.messaging.getToken().then(res => {
if (this.tokensLoaded) {
const existingToken = this.findExistingToken(res);
if (existingToken) {
//Reemplazar token
} else {
//Crear nuevo token
}
}
});
}
findExistingToken(tokenToSave) {
for (let tokenKey in this.allTokens) {
const token = this.allTokens[tokenKey].token;
if (token === tokenToSave) {
return tokenKey;
}
}
return false;
}
// setting tokens "manually"
setToken(val) {
// checking if the token is already in the allTokens array
// and only add the token, if it's not
if (!this.allTokens.includes(val)) this.allTokens.push(val)
return this
}
}
const n = new NoNotificationResource()
n.findExistingToken(123)
console.log(n.setToken(123))
You can declare these two variable i.e., allTokens, tokensLoaded outside the class.
Ex:-
let allTokens = [];
let tokensLoaded = false;
export default class NoNotificationResource {
constructor(messaging, database) {
this.database = database;
this.messaging = messaging;
try {
this.messaging.requestPermission().then(res => {
console.log('Permiso concedido');
}).catch(err => {
console.log('no acces', err);
});
} catch (err) {
console.log('NO hay soporte para notificaciones', err);
};
this.setupTokenRefresh();
this.database.ref('/fcmTokens').on('value', snapshot => {
this.allTokens = snapshot.val();
this.tokensLoaded = true;
})
};
setupTokenRefresh(){
this.messaging.onTokenRefresh(() => {
this.saveTokenToServer();
})
};
saveTokenToServer(){
this.messaging.getToken().then(res => {
if (this.tokensLoaded) {
const existingToken = this.findExistingToken(res);
if (existingToken) {
//Reemplazar token
} else {
//Crear nuevo token
}
}
});
}
findExistingToken(tokenToSave){
for(let tokenKey in this.allTokens){
const token = this.allTokens[tokenKey].token;
if (token === tokenToSave) {
return tokenKey;
}
}
return false;
}
}
Or you can put it inside constructor like this this.allTokens=[];,this.tokensLoaded=false;
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