I'm trying to pass a pointer to a function through the parameters, so the function can update the parameters of the object. The object is bound to the view using {{tasks}} in the tasks.component.html file. Somehow, it looks like the mutations that I do in the provideAndDisplayTasks() function don't change the tasks property in tasks.component.ts at all. I've got similar code that does the same. There it correctly updates the object. I don't understand why it doesn't work in this situation.
How do I update the array, without cloning it?
tasks.component.ts:
private provideAndDisplayTasks() {
const self = this;
self.tasks.push(new Task());
console.log('self.tasks', self.tasks);
this.tasksRepository.provideTasks(self.tasks);
}
tasks-repository.ts:
public provideTasks(tasks: Task[]) {
console.log('parameter', tasks);
this.get('truelime.task/all').subscribe(
data => this.addTasksToTaskArray(tasks, data),
error => {
if (error.status === 401) {
this.router.navigateByUrl('login');
}
Logger.getInstance().logError(error);
}
);
}
private addTasksToTaskArray(tasks: Task[], tasksDto) {
const taskArray = tasksDto.truelime_tasks[0].TrueLime_Task;
for (let i = 0; i < taskArray.length; i++) {
const taskDto = taskArray[i];
const task = new Task();
task.id = taskDto.TaskID;
task.title = taskDto.TaskTitle;
task.description = taskDto.TaskDescription;
task.status = taskDto.TaskStatus;
tasks.push(task);
console.log('tasks', tasks);
}
}
Console logs:
Related
The value of the object is updated very strangely.
the current overall system structure is as follows.
There is a server that collects the status of each system.
Send the collected data from the server to the web server through websocket
When the web server receives the websocket, the callback function is called.
In the callback function, the object is updated with the received data.
The problem occurs when updating objects.
Here is the code for that part.
var systemDatas = {};
...
fn_callback = function(data){
fn_set_metric(data);
...
};
...
function fn_set_metric(data){
Object.entries(data).forEach(([apps, appArr]) => {
for(let i = 0; i < appArr.length; i++){
var app = {};
if(appArr[i].name === "GW"){
if(systemDatas.hasOwnProperty("GW")){
var gwDatas = systemDatas["GW"];
Object.keys(gwDatas).map(function(key){
try {
var keyIdx = 0;
for(let j = 0; j < (appArr[i].nodes).length ; j++){
if(appArr[i].nodes[j].name === key){
keyIdx = j;
break;
}
}
if(appArr[i].nodes[keyIdx].health === "on"){
gwDatas[key].process.cpuSystem = appArr[i].nodes[keyIdx].metrics[0].measurements[0].value;
gwDatas[key].process.cpuProcess = appArr[i].nodes[keyIdx].metrics[1].measurements[0].value;
gwDatas[key].memory.memUsed = appArr[i].nodes[keyIdx].metrics[2].measurements[0].value;
gwDatas[key].memory.heapUsed = appArr[i].nodes[keyIdx].metrics[4].measurements[0].value;
gwDatas[key].thread.threadDeamon = appArr[i].nodes[keyIdx].metrics[6].measurements[0].value;
gwDatas[key].thread.threadLive = appArr[i].nodes[keyIdx].metrics[7].measurements[0].value;
gwDatas[key].memory.memMax = appArr[i].nodes[keyIdx].metrics[3].measurements[0].value;
gwDatas[key].memory.heapMax = appArr[i].nodes[keyIdx].metrics[5].measurements[0].value;
gwDatas[key].thread.threadPeak = appArr[i].nodes[keyIdx].metrics[8].measurements[0].value;
gwDatas[key].process.uptime = appArr[i].nodes[keyIdx].metrics[9].measurements[0].value;
gwDatas[key].process.cpuCount = appArr[i].nodes[keyIdx].metrics[10].measurements[0].value;
console.log(key);
console.log(systemDatas["GW"][key].process.uptime);
console.log(systemDatas["GW"][key].process);
console.log(systemDatas["GW"][key]);
console.log(systemDatas["GW"]);
}
}
catch(e) {
console.error(e);
}
});
}
...
}
and the result of executing the function.
console.log
As you can see in the area marked in yellow in the result image. depending on the scope of the object, the value is different.
my expectation is
after systemDatas["GW"]["GW_1"] is updated, systemDatas["GW"]["GW_2"] is updated. sequentially.
but it's behaving in an incomprehensible way
except the callback function there is no part to update systemDatas.
Can you explain why it works this way?
Your code complexity (nesting) is to high - It is not helping you solve the problem.
Fixes
Break the function up into 2-3 separate functions const parseMetricsData, parseGWData; // etc..
Look over latest added Array methods, some of the new ones like [].find will make the code easier to read (MDN Array Docs).
Other tips after code example.
Example:
const systemDatas = {};
// ...
const fn_callback = function (data) {
fn_set_metric(data);
// ...
};
// ...
const parseGWData = (app, gwDatas) => {
for (const key of gwDatas.keys()) {
const gwData = gwData || {},
foundNode = !app.nodes ? null : app.nodes.find(n => n.name === key);
if (!foundNode || foundNode.health !== 'on') continue;
gwData.process.cpuSystem = foundNode.metrics[0].measurements[0].value;
gwData.process.cpuProcess = foundNode.metrics[1].measurements[0].value;
gwData.process.uptime = foundNode.metrics[9].measurements[0].value;
gwData.process.cpuCount = foundNode.metrics[10].measurements[0].value;
gwData.memory.memUsed = foundNode.metrics[2].measurements[0].value;
gwData.memory.heapUsed = foundNode.metrics[4].measurements[0].value;
gwData.memory.memMax = foundNode.metrics[3].measurements[0].value;
gwData.memory.heapMax = foundNode.metrics[5].measurements[0].value;
gwData.thread.threadDeamon = foundNode.metrics[6].measurements[0].value;
gwData.thread.threadLive = foundNode.metrics[7].measurements[0].value;
gwData.thread.threadPeak = foundNode.metrics[8].measurements[0].value;
console.log(key);
console.table(systemDatas.GW[key])
}
};
function fn_set_metric(data) {
for (const [apps, appArr] of Object.entries(data)) {
for (const app of appArr) {
if (app.name !== 'GW' ||
!Object.prototype.hasOwnProperty.call(systemDatas, 'GW')) continue;
parseGWData(systemDatas.GW);
}
}
}
Other code tips:
Put long property chains into variables, either via built-ins (app.nodes.find(app => app.name === key)) or directly.
Use built-ins (Array.prototype.find, for of loops etc. (use whatever your platform/platform version supports (see MDN Array, etc., for more).
Use negative if checks (instead of nesting main part of code in if statements you can check the opposite condition to avoid creating deeply nested code).
~~Consider not mutating static structures until loops/manipulations are complete; E.g., perform manipulations on pure, new, objects and then merge results into static structure(s) - will help you pinpoint issues~~ Consider that appArr may have duplicate app entries which may be overriding each others' values.
This is a socket.io lobby library for managing the users list.
I created an Array extension class with custom methods. My removeUser method does not work.
Logging shows that inside of the method, it does work - the user has been removed.
Logging outside shows no change.
I believe my issue is one of references. The reference in index.js 'userList' is one reference.
var userList = require("./userList")();
However when I reassign userList in the method, it creates another reference.
userArray = result;
This newly-created reference is not known by the index.js, which sees no change in the userList object.
index.js
My server (simplified for example)
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server);
var userList = require("./userList")();
io.on("connection", (socket) => {
// get user from session
userList.addUser(s_user);
socket.on("disconnect", () => {
userList.removeUser(s_user);
});
});
userList.js (Original)
An extended Array class for managing the list of users in my lobby.
function createUserList() {
let userArray = [];
userArray.addUser = (user) => {
userArray.push(user);
};
userArray.removeUser = (user) => {
let userId = user.user_id;
for (let i = 0; i < userArray.length; i++) {
if (userArray[i]["user_id"] === userId && userId !== undefined) {
let firstHalf = userArray.slice(0, i);
let secondHalf = userArray.slice(i+1, userArray.length);
let result = firstHalf.concat(secondHalf);
userArray = result;
}
}
};
return userArray;
}
My Solution
My solution was to create a closure. An array manager object contains the methods for userList management, and through a closure has access to the userArray. (code below this paragraph)
Pros
The userArray can modified or reassigned without reference issue (within the userList library)
userArray = [] //ok
(I also don't have to re-attach methods on re-assignment)
Cons
I can't use Array prototype methods
let length = userList.length // method doesn't exist on management object
let listCopy = userList // returns an object, not the list
I must use my custom built methods
let length = userList.getLength()
let listCopy = userList.getList()
Does anyone have other interesting solutions?
userList.js (V2)
function createUserList() {
let userArray = []
let arrayManager = {
addUser: (user) => {
userArray.push(user);
},
removeUser: (user) => {
let userId = user.user_id;
for (let i = 0; i < userArray.length; i++) {
if (userArray[i]["user_id"] === userId && userId !== undefined) {
let firstHalf = userArray.slice(0, i);
let secondHalf = userArray.slice(i+1, userArray.length);
let result = firstHalf.concat(secondHalf);
userArray = result;
}
}
},
getList: () => {
return userArray;
},
getLength: () => {
return userArray.length;
}
};
return arrayManager;
}
module.exports = createUserList;
I have written the below code
updatePublication(projectName, publicationId, publicationObj, callback) {
let self = this;
this.initDatabase(function (db) {
let tx = self.db.transaction(self.PUBLICATIONS, self.READ_WRITE);
let store = tx.objectStore(self.PUBLICATIONS);
let index = store.index(self.PROJECT_NAME);
let request3 = index.openCursor(IDBKeyRange.only(projectName));
console.log("hrere");
request3.onsuccess = function () {
let cursor = request3.result;
if (cursor) {
let updateObject = cursor.value;
if (updateObject.publicationID == publicationId) {
updateObject.publicationObject = publicationObj;
cursor.update(updateObject);
callback(publicationId);
}
cursor.continue();
} else {
callback(publicationId);
}
};
});
}
But this give error:
I checked the cause of error. It is beacuse , publicationObj which is passed has an object named _requestObjectBuilder which is of the type Subscriber.
used somewhere in the code like this:
_requestObjectBuilder = interval(1000).pipe(tap(() => {}));
Is there any way i can modify my updatePublication code to ignore this value?
Does indexed db support a query for ignoring a value and saving the data?
Note: If i set publicationObj._requestObjectBuilder = undefined, the data gets saved to indexedDB. But this breaks the functionality where _requestObjectBuilder is used.
Fixed the issue by cloning the object and setting it to undefined
let clonedObject = Object.assign({}, publicationObject);
clonedObject._requestObjectBuilder = undefined;
Now i am updating the clonedObject
I have two separate files, the first being a component (List.js) that uses the second (APIService.js) to fetch different APIs. To correct fetch, the URL needs to receive global variables. Right now, I am trying to redefine these variables from a function in the APIService file without success. Variables are being redefined in APIService.js just before the API calls comment.
I have two questions:
Why is the global variable naptanId not being redefined?
Would be possible to define and pass these variables from the component?
Pseudo-code
Detects beacon
Redefine naptanId
Component fetch API using recently defined variable
API call is done
Data is passed back to Component
Set states
List.js
componentDidMount() {
// Executes first function
APIService._fetchStopPoint((resp1) => {
console.log("Stoppoint", resp1)
// ... and set the bus state with the first response
this.setState({
bus: resp1
});
// ... based on the response, convert array to string
const lines = (resp1.lines.map((line) => line.name)).toString()
// ... pass lines to sencond function
APIService._fetchArrivalTimes(lines, (resp2) => {
// .. and set the tube state with the second response
this.setState({
isLoading: false,
tube: resp2
});
});
});
}
APIService.js
// Variables
// ***********************************************************************
let naptanId = undefined
let lines = undefined
let ice = '59333'
let mint = '57011'
let blueberry = '27686'
let nearestBeacon = undefined;
let newBeaconId = undefined;
let setIce = false;
let setBlueberry = false;
let setMint = false;
// Beacon detection
// ***********************************************************************
const region = {
identifier: 'Estimotes',
uuid: '354A97D8-9CAF-0DC7-CE0E-02352EBE90CD',
};
// Request for authorization while the app is open
Beacons.requestWhenInUseAuthorization();
Beacons.startMonitoringForRegion(region);
Beacons.startRangingBeaconsInRegion(region);
Beacons.startUpdatingLocation();
// Listen for beacon changes
const subscription = DeviceEventEmitter.addListener('beaconsDidRange', (data) => {
const ibeacons = data.beacons
// var lowestAccuracySeen = 0.5;
let lowestAccuracySeen = "immediate"
// Check if beacons are updating
if (ibeacons && ibeacons.length > 0) {
// Loop through beacons array
for (var i = 0; i < ibeacons.length ; i++) {
// Find beacons with same minor ...
var foundBeacon = ibeacons.find(function(closestBeacon) {
// ... and return the beacon the lowest accuracy seen
// return closestBeacon.accuracy.toFixed(2) < lowestAccuracySeen;
return closestBeacon.proximity == lowestAccuracySeen
});
// If found ...
if (foundBeacon) {
// ... define the lowest accuracy and the nearest beacon
lowestAccuracySeen = foundBeacon.accuracy;
nearestBeacon = foundBeacon;
// Identify what component to render against nearest beacon
setIce = nearestBeacon.minor == ice ? true : false;
setMint = nearestBeacon.minor == mint ? true : false;
setBlueberry = nearestBeacon.minor == blueberry ? true : false;
if (setIce) {
// THESE VARIABLES CANNOT BE REDEFINED
naptanId = "490004936E"
lines = "55"
} else if (setMint) {
} else if (setBlueberry) {
};
}
}
}
});
// API calls
// ***********************************************************************
class APIService {
// Fecth stop point info
static _fetchStopPoint(cb) {
console.log(naptanId, lines)
fetch(`https://api.tfl.gov.uk/StopPoint/${naptanId}`)
.then(stopData => {
try {
stopData = JSON.parse(stopData._bodyText); // Converts data to a readable format
cb(stopData, naptanId);
} catch(e) {
cb(e);
}
})
.catch(e => cb(e));
}
// Fetch arrival times info
static _fetchArrivalTimes(lines, cb) {
fetch(`https://api.tfl.gov.uk/Line/${lines}/Arrivals/${naptanId}`)
.then(arrivalData => {
try {
arrivalData = JSON.parse(arrivalData._bodyText);
arrivalTime = arrivalData
cb(arrivalData);
} catch(e) {
cb(e);
}
})
.catch(e => cb(e));
}
// Fetch status info
static _fetchStatus(lines) {
fetch(`https://api-argon.digital.tfl.gov.uk/Line/${lines}/Status`)
.then(statusData => {
try {
statusData = JSON.parse(statusData._bodyText); // Converts data to a readable format
cb(statusData);
} catch(e) {
cb(e);
}
})
.catch(e => cb(e));
}
}
module.exports = APIService;
The simplest approach to handle these global variables (cross different components) is to use AsyncStorage:
let response = await AsyncStorage.getItem('listOfTasks'); //get, in any components
AsyncStorage.setItem('listOfTasks', 'I like to save it.'); //set, in any components
For more performance critical global vars, you can also consider Realm Database (Like CoreData, SQLite in both iOS and Android).
I declared a global array in index.js (firebase function). Once the code is deployed, this array is filled from firebase data.
I have two functions, in the first one (onTW) i made some changes to the array, and i'm just displaying it in the other function(onRemoveTW). The problem is I'm getting an empty array in the second function.
Here's my code.
var TWArray = [];
TWRef.once('value', function (snapshot) {
snapshot.forEach(function(childSnapshot) {
var name=childSnapshot.key;
var users = {};
var userNbr = 0;
TWRef.child(name).child('rm').once('value', function (snapshot2) {
snapshot2.forEach(function(childSnapshot2) {
userNbr++;
if(childSnapshot2.key=='a'){
users.a = childSnapshot2.val();
}
if(childSnapshot2.key=='b'){
users.b = childSnapshot2.val();
}
if(childSnapshot2.key=='c'){
users.c = childSnapshot2.val();
}
if(childSnapshot2.key=='d'){
users.d = childSnapshot2.val();
}
})
TWArray.push({
rmName:name,
users:users,
userNbr:userNbr
});
})
})
})
exports.onTW = functions.database
.ref('/Orders/TW/{requestId}')
.onWrite(event => {
const userKey = event.data.key;
const post = event.data.val();
if (post != null) {
var users={};
users.a=userKey;
TWArray.push({
rmName:userKey,
users:users,
userNbr:1
});
console.log(TWArray);
console.log("TWArray.length : "+TWArray.length);
}
});
exports.onRemoveTW = functions.database
.ref('/Orders/RemoveTW/{requestId}')
.onWrite(event => {
const userKey = event.data.key;
const post = event.data.val();
if (post != null) {
console.log("TWArray.length : "+TWArray.length);
}
})
Thanks in advance!
You cannot share data between functions by writing to global variables when using firebase-functions, because they intended to be stateless. As such, this functionality is not supported.
What you can do is write your data to firebase-database instead.