fail Failed to execute 'send' on 'WebSocket': Still in CONNECTING state - javascript

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

Related

How to fix refresh access token from the first http request which gives GET 401 error

The problem is that, when the access token is expired and I do any click, then access token does not refresh. But when I do the second click, it refreshes. For the first click, I get 'GET 401 error'. The actual problem for me is to get access token before any HTTP request in the interceptor.
I tried switchMap for my code to wait for the access token, but it didn't work.
Do you have any ideas how could I fix this?
export class DevelopmentInterceptor implements HttpInterceptor {
constructor(
private authService: AuthService,
private router: Router,
private toastr: ToastrService,
private translate: TranslateService
) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headers = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8',
'Authorization': `Bearer ${this.authService.getAccessToken()}`
});
let apiReq = null;
if (req.url.indexOf('i18n') >= 0) {
apiReq = req;
} else if (req.url.indexOf('token') >= 0) {
apiReq = req.clone({ url: environment.authServerUrl + `${req.url}` });
} else if (req.url.indexOf('sign-up') >= 0) {
apiReq = req.clone({ url: environment.signupUrl });
} else if (req.url.indexOf('api/users') >= 0 || req.url.indexOf('api/roles') >= 0 || req.url.indexOf('api/permissions') >= 0) {
apiReq = req.clone({ headers: headers, url: environment.authServerUrl + `${req.url}` });
} else {
apiReq = req.clone({ headers: headers, url: environment.backenUrl + `${req.url}` });
}
if (req.url.endsWith('token')) {
return next.handle(apiReq).catch((err: any) => { //<--if error use a catch
if (err instanceof HttpErrorResponse) {
return this.handleError(err);
}
});
} else {
return this.authService.checkExpiry().switchMap( (result) => {
if (result) {
return next.handle(apiReq)
.catch((err: any) => { // <--if error use a catch
if (err instanceof HttpErrorResponse) {
return this.handleError(err);
}
});
}
} )
}
}
private handleError(err: Response | any) {
...
}
}
public checkExpiry() : Observable<any> {
if (!this.cookieService.get('user_id')) {
this.removeTokens(); // not logged in
return Observable.of(true);
} else if (!this.cookieService.check('access_token')) {
if (this.cookieService.check('refresh_token')) {
if (this.secondsTillExpiry('refresh_token') > 0) {
return this.refreshAccessToken().switchMap((data:any) => {
if (data) {
this.saveTokenInCookies(data);
this.updateExpiration(data);
return Observable.of(true);
}
})
} else {
this.router.navigate(['/login']);
this.removeTokens();
return Observable.of(true);
}
}
} else if (this.cookieService.check('access_token') ) {
return Observable.of(true);
}
}
public secondsTillExpiry(tokenMode: string): any {
if (tokenMode == 'access_token') {
return ((new Date(1970, 0,
1).setSeconds(jwt_decode(this.getAccessToken()).exp)) -
(Math.round(Date.now()) / 1000));
} else if (tokenMode == 'refresh_token') {
return ((new Date(1970, 0,
1).setSeconds(jwt_decode(this.getRefreshToken()).exp)) -
(Math.round(Date.now()) / 1000));
}
}
private refreshAccessToken(): Observable<Object> {
const params = 'refresh_token=' + this.getRefreshToken() +
'&grant_type=refresh_token';
return this.http.post(this.authUrl, params, this.getOptions());
}
you can also check expire token before send any request in CanActivate and if it's valid token so user can is navigated to required route else it will be redirected to login
here is an example to handle this
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
let accesstoken: string = next.queryParams.accesstoken;
if (this.authService.IsAuthenticated) {
let user = this.authService.GetUser();
let CurrentDate = new Date();
let date = CurrentDate.getFullYear() + "-" + (CurrentDate.getMonth() + 1) + "-" + CurrentDate.getDate();
if (user.expire_date) {
if (Date.parse(date) <= Date.parse(user.expire_date)) {
if (accesstoken) {
// if token in url, redirect to url without token :)
if (user.uuid == accesstoken)
this.router.navigateByUrl(window.location.pathname);
// if new token is not the same of current one, Register with new token
else {
return this.authService.checkAccess(accesstoken).pipe(
map(data => {
if (data === true) {
if (accesstoken) {
this.router.navigateByUrl(window.location.pathname);
}
return true;
} else {
this.router.navigate(['/login']);
return false;
}
})
);
}
}
return true;
}
else if (Date.parse(date) > Date.parse(user.expire_date)) {
this.router.navigate(['/login']);
return false;
}
}
}
else {
this.router.navigate(['/login']);
return false;
}
}
you should process it according to your code

Not able to join a group channel on Sendbird

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

Possible Unhandled Promise Rejection (id: 0): Error missing baseUrl

I'm getting this error every time I press a specific button on my react-native app. I'm guessing it has to do something with an Api call or maybe it is trying to invoke URLs with localhost:8081, which may not be correct as it should be pointing to a server. I'm not sure exactly how to pinpoint the problem. Any help would be much appreciated. I'm also now sure if the problem is coming from the file I shared underneath.
App Warning message:
This is my RestClient code:
import {Alert, AsyncStorage} from 'react-native'
import {resetRouteTo} from 'util/NavigationHelper'
import {store} from '../index.js'
import {dropdownAlert} from 'util/AlertManager'
const DEFAULT_ERROR = {error: {code: 500, message: 'No JSON message'}}
export default class RestClient {
constructor (baseUrl = '', navigation, { headers = {}, devMode = false, simulatedDelay = 0 } = {}) {
if (!baseUrl) throw new Error('missing baseUrl')
this.navigation = navigation
this.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
Object.assign(this.headers, headers)
this.baseUrl = baseUrl
this.simulatedDelay = simulatedDelay
this.devMode = devMode
}
_clearTokenAndGo () {
AsyncStorage.removeItem('apiToken')
Alert.alert(
'Error',
'Something went wrong and your account needs to be re-instantiated.',
[
{text: 'OK', onPress: () => resetRouteTo(this.navigation, 'OnboardingFirst')}
],
{ cancelable: false }
)
}
_simulateDelay () {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, this.simulatedDelay)
})
}
async _parseIfJson (response) {
var contentType = response.headers.get('content-type')
if (contentType && contentType.indexOf('application/json') !== -1) {
return response.json()
}
return null
}
async _handleError (response) {
const body = await this._parseIfJson(response)
if (!body) {
dropdownAlert('error', `Server Error ${response.status}`, 'Something went wrong on the server')
return DEFAULT_ERROR
}
switch (response.status) {
case 200: {
break
}
case 401: {
if (body.error === 'Unauthenticated.') {
this._clearTokenAndGo()
}
break
}
case 400: {
dropdownAlert('error', `Error ${body.error.code}`, body.error.message)
break
}
default: {
if (body.error) {
dropdownAlert('error', `Error ${body.error.code}`, body.error.message)
} else {
dropdownAlert('error', 'Error', `An unknown error has occurred. Http status ${response.status}`)
}
break
}
}
return body
}
_fullRoute (url) {
return `${this.baseUrl}${url}`
}
async _fetch (route, method, body, isQuery = false) {
if (!route) throw new Error('Route is undefined')
if (!store.getState().netinfo.isConnected) {
this.navigation.navigate('BlockScreen')
return {success: false, error: {code: 1, message: 'No internet connection.'}}
}
var fullRoute = this._fullRoute(route)
if (isQuery && body) {
var qs = require('qs')
const query = qs.stringify(body)
fullRoute = `${fullRoute}?${query}`
body = undefined
}
let opts = {
method,
headers: this.headers
}
if (body) {
Object.assign(opts, { body: JSON.stringify(body) })
}
const fetchPromise = () => fetch(fullRoute, opts)
if (this.devMode && this.simulatedDelay > 0) {
// Simulate an n-second delay in every request
return this._simulateDelay()
.then(() => fetchPromise())
.then(response => response.json())
} else {
let promise = await fetch(fullRoute, opts)
console.log('Logging response =>')
console.log(promise)
return this._handleError(promise)
}
}
GET (route, query) { return this._fetch(route, 'GET', query, true) }
POST (route, body) { return this._fetch(route, 'POST', body) }
PUT (route, body) { return this._fetch(route, 'PUT', body) }
DELETE (route, query) { return this._fetch(route, 'DELETE', query, true) }
}
Other files using RestClient:
import RestClient from 'util/RestClientLib'
import qs from 'qs'
import { Linking, AsyncStorage } from 'react-native'
import Config from 'react-native-config'
var SHA256 = require('crypto-js/sha256')
export default class ApiClient extends RestClient {
constructor (authToken, navigation) {
console.log('constructing apiClient with base: ', Config.API_URL)
super(Config.API_URL, navigation, {
headers: {
'Authorization': 'Bearer ' + authToken
}
})
}
_switchSchemeTo (url, scheme) {
var split = url.split(':')
split[0] = scheme
return split.join(':')
}
_makeAppUrl (url) {
const prefix = url.split('.')[0]
const bank = prefix.substr(prefix.lastIndexOf('/') + 1, prefix.length)
switch (bank) {
case 'florijnbank':
return this._switchSchemeTo(url, 'flrb')
default:
return url
}
}
async _openUrl (url) {
const openInApp = await AsyncStorage.getItem('openInApp')
const appUrl = this._makeAppUrl(url)
Linking.canOpenURL(appUrl).then(supported => {
if (!supported || openInApp !== 'true') {
Linking.canOpenURL(url).then(supported => {
if (!supported) {
console.log('Can\'t handle url: ' + url)
} else {
Linking.openURL(url)
}
}).catch(err => console.error('An error occurred', err))
} else {
Linking.openURL(appUrl)
}
}).catch(err => console.error('An error occurred', err))
}
async createToken (pin) {
var hash = SHA256(pin).toString()
const query = {pincode: hash}
let response = await this.POST('/user', query)
return response.api_token
}
async checkPin (pin) {
const hash = SHA256(pin).toString()
const query = {pincode: hash}
return this.GET('/user/validate', query)
}
getAccounts () {
return this.GET('/account')
}
getBalance (iban) {
return this.GET(`/account/${iban}`)
}
async getPermissionBank (bank) {
const query = {
bank_id: bank
}
let response = await this.POST('/account', query)
return this._openUrl(response.url)
}
postCredentialsAis (form) {
return this.POST('/account/password', form)
}
async ais (iban) {
let response = await this.GET(`/ais/${iban}`)
if (response.url == null) {
return true
}
this._openUrl(response.url)
return false
}
getTransactionDetails (requestId) {
return this.GET(`/request/${requestId}`)
}
getTransactions (iban) {
return this.GET(`/account/${iban}/transaction`)
}
getContacts () {
return this.GET('/contacts')
}
getSettings () {
return this.GET('/startup')
}
deleteAccount (iban) {
return this.DELETE(`/account/${iban}`)
}
/**
* async submitTransfer - submits a transfer
*
* #param {Object} options object which holds the pin, iban, sso and query
* #param {Object} transfer hold the transfer information
* #return {Boolean} either opens a link or a boolean for success
*/
submitTransfer (iban, credentials, transfer) {
const url = `/account/${iban}/transaction?${qs.stringify(credentials)}`
const body = {
counter_iban: transfer.counterIban,
counter_account_name: transfer.name,
amount: transfer.amount,
description: transfer.description,
reference: transfer.reference
}
return this.POST(url, body)
}
qrConfirmTransfer (transactionId, iban, credentials) {
const url = `/request/${transactionId}/confirm/${iban}?${qs.stringify(credentials)}`
return this.POST(url)
}
directConfirmTransfer (transactionId, iban, form) {
const url = `/account/${iban}/transaction/${transactionId}`
return this.POST(url, form)
}
verificationRequired (iban, amount) {
const query = {amount: amount}
return this.GET(`/veriReq/${iban}`, query)
}
};

trying to call MVC Get Action from Angular 2 with typescript

I have a simple MVC Get method as below to get a Customer Id from the Session
[HttpGet]
public string GetCustomerId()
{
return Session["CUSTOMERID"].ToString();
}
If I hit this URL directly in the browser
http://localhost/myApp/Home/GetCustomerId I can set a breakpoint int the method and it gets hit and I get the value returned.
However, I need to call the method from my Client code which is Angular 2 written in typescript. My Typescript method is as below - I cannot get it to hit the MVC Breakpoint even though I am logging the exact same URL as above to the console.
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
**UPDATE To include entire Typescript service
import { Injectable, Output, EventEmitter } from '#angular/core';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { EnvironmentService } from '../common/environment.service';
import { AppSettings } from '../common/app-settings';
#Injectable()
export class SessionService {
#Output() public gSession: EventEmitter<any> = new EventEmitter();
private sessionTime: number = 1500000; // 25 minute
constructor(private http: Http, private environmentService: EnvironmentService) {
}
public setValue(isLoading: boolean): void {
this.gSession.emit(isLoading);
}
public getValue(): any {
return this.gSession;
}
public startSession(): void {
this.getCustomerIdFromSession();
let timeoutId = setTimeout(() => {
this.setValue(true);
}, this.sessionTime);
}
public getCustomerIdFromSession() {
console.log('get customer from session called');
let srv = this.environmentService.getCurrentEnvironment();
let httpOrHttps = '';
if (srv === AppSettings.ENV_LOCALHOST) {
httpOrHttps = AppSettings.URL_HTTP;
}
else {
httpOrHttps = AppSettings.URL_HTTPS;
}
let baseUrl = httpOrHttps + srv + AppSettings.URL_GET_CUST_FROM_SESSION;
console.log(baseUrl); //this logs - http://localhost/myApp/Home/GetCustomerId
return this.http.get(baseUrl)
.catch(this.handleError);
}
public handleError(error: Response) {
console.log("error");
return Observable.throw(error.json() || 'Server Error');
}
public extractData(res: Response) {
console.log("In extract method");
let body = res.json();
console.log(body);
if (body) {
return body.data || body;
} else {
return {};
}
}
}
You are not mapping the response.
return this.http
.get(baseUrl)
.map(this.extractData)
.catch(this.handleError);
private extractData(res: Response) {
let body = res.json();
if (body) {
return body.data || body;
} else {
return {};
}
}
You have to map the response and process it with json() if you know that will be a JSON or with text(). Usually will be JSON.
I took the liberty of adding a response handler such as extractData. You could just json() the response directly if you wanted.

Angular 2 Firebase CRUD using ReplaySubject

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');
});
}

Categories