Rxjs BehaviorSubject error handling when used with mergemap - angular7

I have the following code
#Injectable()
export class ReceptionService {
private generalInfoDataSrc$ = new BehaviorSubject<any>(null);
public generalInfoData = this.generalInfoDataSrc$.asObservable();
setGeneralInfo(dataSrc: GeneralInfoMModal) {
this.generalInfoDataSrc$.next(dataSrc);
}
}
From my component1 I will set the above as
OnSelect(patient: any) {
let generalInfo = new GeneralInfoMModal();
generalInfo.id = patient.id;
// some other code here
// this.recepService.setGeneralInfo(generalInfo);
}
// from component2
//
ngOnInit() { getPatientDetails() }
getPatientDetails() {
this.receptionService.generalInfoData.pipe(mergeMap(response => {
if (response && response.id) {
this.loading = true;
return this.receptionService.get('User/Get' + response.id, this.sourceobj);
} else {
return of(null);
}
}), takeUntil(this.unsubscribe$)).subscribe(response => {
this.patient = response;
this.loading = false;
}, error => {
this.loading = false;
// this.utility.showMsg('An error occurred while getting user.')
}, () => {
})
}
Every things works well. I keep on selecting a user thereby calling the User/Get api. But if in case if the api returns an error then error part is executed after which when there is a change in behaviorsubject(user is selected) it doesn't call the User/Get. Is there other way of handling errors with behaviorsubject or any other approach to handle the idea. How a behaviorsubject should be used in such a case.

If you are using the same behavior subject over and over again, and if there is an error, you need to set the behavior subject back to null, so that when the next user is set, it will get the latest value.
Try something like this:
getPatientDetails() {
this.receptionService.generalInfoData.pipe(mergeMap(response => {
if (response && response.id) {
this.loading = true;
return this.receptionService.get('User/Get' + response.id, this.sourceobj);
} else {
return of(null);
}
}), takeUntil(this.unsubscribe$)).subscribe(response => {
this.patient = response;
this.loading = false;
}, error => {
this.loading = false;
///////////////////////////////// ADD THIS LINE ///////////////////////
this.recepService.setGeneralInfo(null);
// this.utility.showMsg('An error occurred while getting user.')
}, () => {
})

Related

Netlify functions with axios

I want to make my form submission happen server-side in order to not expose my API key. I plan to do this with netlify functions however I don't know how that would look with Axios. I've looked for examples on how to do this but I don't seem to find any. Could some help me I'm stuck as to what to put inside my the Netlify function? If anyone has worked with these two programs and could provide a hand that would be helpful here is my javascript with my submission function.
var form = document.querySelector("#user_form");
let reqHeaders = {
headers: {
Authorization: "Bearer",
}
}
let url = ""
let reqData = {
records: [
{
fields: null
}
]
}
let formData = {
firstName: "",
lastName: "",
email: ""
}
function logData(id, dataObj, value) {
dataObj[id] = value;
console.log(value)
}
function formMessg (id) {
document.querySelector(id).style.display = "block";
setTimeout(function(){
document.querySelector(id).style.display = "none";
form.reset();
}, 2500)
}
form.addEventListener("submit", function (e) {
e.preventDefault();
let spam = document.getElementById('spam').value;
try {
for(const data in formData){
if(formData[data] === "" || spam.length !== 0){
const error = new Error();
error.notVaild = true;
throw error;
}
}
reqData.records[0].fields = formData;
console.log(reqData);
axios.post(url, reqData, reqHeaders).then((res) => {
formMessg ('.success-messg');
form.style.display = "none";
})
.catch ((err) => {
throw err;
});
} catch (err){
if (err.reponse){
formMessg ('.fail-messg');
} else if (err.request) {
formMessg ('.fail-messg');
} else if ("Notvalid") {
formMessg ('.fill-messg');
}else {
console.log(err);
}
}
});

While trying to have group video chat using the opentok multiple stream with null streamId gets added and video goes blank some time

I am trying to implement group video functionality and I have following code
class App extends Component {
this.state = {
subscribers: [],
subscriberVideos: [],
screenVideo: undefined,
publisherVideo: undefined,
publisher: undefined,
}
}
async start() {
let publisher = OT.initPublisher(null, this.defaultPublisherProps, error => {
if(error) {
}
})
publisher.on('videoElementCreated', this.onPublisherVideoElement);
this.state.otSession.publish(publisher, error => {
if (error) {
}
this.setState(() => {
return { publisher: publisher };
}
}
}
onPublisherVideoElement = event {
this.setState(() => {
return { publisherVideo: event.element }
});
}
}
onPublisherScreenElement = event => {
this.setState(() => {
return { screenVideo: event.element }
}
}
onSubscriberVideoElement = event => {
this.setState(() => {
return {
subscriberVideos: [...this.state.subscriberVideos, event.element]
}
}
})
}
onSessionStreamCreated = event => {
let subscriber = this.state.otSession.subscriber(event.stream, null, this.defaultSubscriberProps, error => {
if (error) {
}
if (event.stream.videoType == 'screen') {
subscriber.on('videoElementCreated', this.onPublisherScreenElement);
this.setState(() => {
return { screenSubscriber: subscriber };
})
} else {
subscriber.on('videoElementCreated', this.onSubscriberVideoElement);
if (this.props.mdm === "m") {
this.setState((prevState) => {
return {
subscribers: [...this.state.subscribers, subscriber]
}
}
}
else {
return { subscribers: [...this.state.subscribers, subscriber] }
}
}
}
}
While showing subscribers I am doing
showSubscribers() {
return this.state.subscribers.filter(subscriber => subscriber.stream !== null).map((subscriber, index) => {
return(
<VideoSubscriber
key={index}
otok={this.otok}
subscriber={this.state.subscribers[index]
subscriberVidoe={this.state.subscriberVideos[index]
/>
)
}
}
But at random times the video goes black and also while some of the subscriber refresh the page it goes blank creates multiple subscirber with null stream.
How can i resolve this?
I think you probably want to handle the 'streamDestroyed' event and remove your subscribers. This is probably why you're getting blank subscribers when people leave.
Also video going black randomly could be happening because you're falling back to audio-only mode. This happens if your network has lots of packet loss, then it will drop the video and try to only send audio. You can handle the videoDisabled event and look at the reason 'quality'. More details here

Aurelia fetch client not receiving data from controller

I'm trying to load a database in a controller(asp.net MVC) and then using the aurelia fetch client to load the data from the controller into the view but no data is being fetched by aurelia(view tables are empty which isn't the result when manually declaring an array of inputs)
EmployeesController(Controller)
using Microsoft.AspNetCore.Mvc;
using SPAproject.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SPAproject.Controllers
{
[Route("api/[controller]")]
public class EmployeesController : Controller
{
private readonly EmployeesDbContext context;
public EmployeesController(EmployeesDbContext context)
{
this.context = context;
}
[HttpGet]
public IEnumerable<Employee> Get()
{
return context.Employees.ToList();
}
}
}
emp-api(where I'm fetching the data)
import { HttpClient } from 'aurelia-fetch-client';
import { inject } from 'aurelia-framework';
let latency = 200;
let id = 0;
#inject(HttpClient)
export class EmpAPI {
isRequesting = false;
constructor(http) {
this.http = http;
this.http.configure(config =>
config.useStandardConfiguration()
.withDefaults({
mode: 'cors'
}
)
);
this.employees = [];
http.fetch('/api/Employees')
.then(x => x.json())
.then(employees => this.employees = employees);
}
getEmployeeList() {
this.isRequesting = true;
return new Promise(resolve => {
setTimeout(() => {
let results = this.employees.map(x => {
return {
id: x.id,
firstName: x.firstName,
lastName: x.lastName,
email: x.email
}
});
resolve(results);
this.isRequesting = false;
}, latency);
});
}
getEmployeeDetails(id) {
this.isRequesting = true;
return new Promise(resolve => {
setTimeout(() => {
let found = this.employees.filter(x => x.id == id)[0];
resolve(JSON.parse(JSON.stringify(found)));
this.isRequesting = false;
}, latency);
});
}
saveEmployee(employee) {
this.isRequesting = true;
return new Promise(resolve => {
setTimeout(() => {
let instance = JSON.parse(JSON.stringify(employee));
let found = this.employees.filter(x => x.id == employee.id)[0];
if (found) {
let index = this.employees.indexOf(found);
this.employees[index] = instance;
} else {
instance.id = getId();
this.employees.push(instance);
}
this.isRequesting = false;
resolve(instance);
}, latency);
});
}
}
employee-list(where I'm trying to get the data to from API)
import { EventAggregator } from 'aurelia-event-aggregator';
import { EmpAPI } from 'emp-api';
import { inject } from 'aurelia-framework';
import { EmployeeUpdated } from 'employeeUpdated';
import { EmployeeViewed } from 'employeeViewed';
#inject(EmpAPI, EventAggregator)
export class EmployeeList {
constructor(api, ea) {
this.api = api;
this.ea = ea;
this.employees = [];
ea.subscribe(EmployeeViewed, msg => this.select(msg.employee));
ea.subscribe(EmployeeUpdated, msg => {
let id = msg.employee.id;
let found = this.employees.find(x => x.id == id);
Object.assign(found, msg.employee);
});
}
created() {
this.api.getEmployeeList().then(employees => this.employees = employees);
}
select(employee) {
this.selectedId = employee.id;
return true;
}
}
Either you can use one of their wrapper methods like http.get('/api/Employees') in this case.
If you want to use fetch, then you need to specify a method http.fetch('/api/Employees', {method: 'GET'})
The issue you see is because you didn't wait for your data to return. By the time your employee-list element is created, employees property in your EmpAPI is still undefined, as your data fetching call hasn't been returned yet.
I see that you have 200 ms latency to prevent this from happening, but sometimes maybe that is not enough (I suspect this). Maybe you can try a different latency if you want to keep this strategy? There are different ways to do this, like only resolve the getEmployeeList() promise only when the data fetching call has already been resolved, delay the call further, wait for the call etc.

Passing String parameter Value Through angular Service parameter Value is Automatically Appends Some Special Character

Here's my Angular controller
//Save And Update
$scope.AddUpdateBusinessType = function() {
var businessType = {
Code: $scope.businessCode,
BusiType: $scope.businessType
};
var getBusinessTypeAction = $scope.BusinessTypeAction;
if (getBusinessTypeAction == "Update") {
businessType.BusinessTypeId = $scope.businessTypeId;
var getBusinessTypeData = businessTypeService.updateBusinessType(businessType);
getBusinessTypeData.then(function (msg) {
GetAllBusinessType();
$scope.ClearBusinessTypeForm();
alert("Record Updated Successful");
$scope.BusinessTypeAction = "";
$scope.divBusinessType = false;
}, function () {
alert('Error in Updating Record');
});
} else {
**// Save Section**
var getExistBusinessCode = businessTypeService.checkBusinessTypeCode(businessType.Code);
getExistBusinessCode.then(function (businessTypeCode) {
debugger;
if (businessTypeCode == true) {
alert('Business Type Code Already Exist');
} else {
debugger;
var getBusinessTypeData = businessTypeService.addBusinessType(businessType);
getBusinessTypeData.then(function (msg) {
GetAllBusinessType();
$scope.ClearBusinessTypeForm();
alert("Record Added Successful");
$scope.divBusinessType = false;
}, function () {
alert("Error Occured In Saving Data");
});
}
},function() {
alert('Error Occured While Checking Records');
});
}
}
In the above code Save Section I am trying to check if a value is exists in a database so I'm passing a string value to: checkBusinessTypeCode(businessType.Code) Service.When I Debug and See Value its Seems Normal.
Here's My Service:
//Check Business Code
this.checkBusinessTypeCode = function (businessTypeCode) {
debugger;
var response = $http({
method: "post",
url: "/BusinessType/CheckBusinessTypeDetailByCode",
params: {
businessTypeCode: JSON.stringify(businessTypeCode)
}
});
return response;
}
But when Passing To Controller string value I get some unexpected behavior.
two \\ always appear automatically
example
"\"stringvalue\""
I'm Still Having Above Problem
but as a quick solution i did code as follows
public bool _CheckBusinessTypeDetailByCode(string businessTypeCode)
{
string bisCode = businessTypeCode.Replace("\"", "");
bool isExist;
isExist = _IBusinessTypeRepository.IsExist(x => x.IsActive && !x.IsDelete && x.Code == bisCode);
return isExist;
}
I don't know is it bad practice or not , any way it is solved my problem.
Before did this modification
string businessTypeCode always gives value as
"\"somevalue\""

Make function to return custom stream

Is it possible to create a function that returns a custom stream and handles it like this?
user.logIn('owner', '1234')
.listen(
success (Object user) {
print(user);
},
error: (Object user, Object error) {
print(error);
}
);
Something like:
class LoginResult {
bool success = false;
String username;
}
Stream<LoginResult> onLogin() async* {
while(...) {
yield new LoginResult()
..success = isSuccess
..userName = 'someUser';
}
}
or
StreamController<LoginResult> onLoginController = new StreamController<LoginResult>();
// might not be necessary if you only need one listener at most
Stream<LoginResult> _onLogin = onLoginController.stream.asBroadcastStream();
Stream<LoginResult> get onLogin => _onLogin
...
onLoginController.add(new LoginResult()
..success = isSuccess
..userName = 'someUser');
Then you can use it like

Resources