I have a route that sends to me many requests over time, that contain data to stored in a model.
So the first request does not contain all the needed data and I need to parse each request every time new information comes and store it.
Actually I have a separate js file which contains the "model" and methods
const request = require('request-promise');
function Conversation(param) {
console.log(param)
this.endpoint ;
this.id = this.getConvId(param);
this.createdOn = Date.now();
this.to = this.getTo(param);
this.from = this.getFrom(param);
this.state = this.getState(param);
this.importance = this.getImportance(param);
this.threadId = this.getT;
this.subject = this.getSubject(param);
this.name=this.getName(param);
}
Conversation.prototype.sendIM =function sendIM(param) {
// method to send message to a user
}
Conversation.prototype.getConvId = function getConvId(param) {
return param.operationId
};
Conversation.prototype.getTo = function getTo(param) {
return param.to
}
Conversation.prototype.getDirection = function getDirection(param) {
return param.direction
}
Conversation.prototype.getState = function getState(param) {
return param.state
}
Conversation.prototype.getOperationId = function getOperationId(param) {
return param.sender[0].events[0]._embedded["service:messagingInvitation"].opertionId
}
Conversation.prototype.getImportance = function getSubject(param) {
return param.importance;
}
Conversation.prototype.getSubject = function getSubject(param) {
return param.sender[0].events[0]._embedded["service:messagingInvitation"].subject
}
Conversation.prototype.getFrom= function getFrom(param) {
return param._embedded["localParticipant"].uri
}
Conversation.prototype.getName= function getName(param) {
return param._embedded["acceptedByParticipant"].name
}
module.exports = Conversation;
In my main app file I create a new conversation object:
var Conversation= require('./Conversation');
app.post('/callback', function (req, res) {
if(req.body.sender.length==0) {
res.status(200).send();
}
if(req.body.sender.length>0) {
const conv = new Conversation(req.body.sender[0].events[0]._embedded['service:messagingInvitation']);
res.status(200).send();
}
})
the method works well when I have to fill the model once, but when I update an item it becomes complicated.
So I would like to know what is the best way to structure my files so that I will be able to add new data to my model over time ?
Related
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 have a node/express server and I'm trying to get a function from a helper file to my app.js for use. Here is the function in the helper file:
CC.CURRENT.unpack = function(value)
{
var valuesArray = value.split("~");
var valuesArrayLenght = valuesArray.length;
var mask = valuesArray[valuesArrayLenght-1];
var maskInt = parseInt(mask,16);
var unpackedCurrent = {};
var currentField = 0;
for(var property in this.FIELDS)
{
if(this.FIELDS[property] === 0)
{
unpackedCurrent[property] = valuesArray[currentField];
currentField++;
}
else if(maskInt&this.FIELDS[property])
{
//i know this is a hack, for cccagg, future code please don't hate me:(, i did this to avoid
//subscribing to trades as well in order to show the last market
if(property === 'LASTMARKET'){
unpackedCurrent[property] = valuesArray[currentField];
}else{
unpackedCurrent[property] = parseFloat(valuesArray[currentField]);
}
currentField++;
}
}
return unpackedCurrent;
};
At the bottom of that helper file I did a module.export (The helper file is 400 lines long and I don't want to export every function in it):
module.exports = {
unpackMessage: function(value) {
CCC.CURRENT.unpack(value);
}
}
Then in my app.js I called
var helperUtil = require('./helpers/ccc-streamer-utilities.js');
and finally, I called that function in app.js and console.log it:
res = helperUtil.unpackMessage(message);
console.log(res);
The problem is that the console.log gives off an undefined every time, but in this example: https://github.com/cryptoqween/cryptoqween.github.io/tree/master/streamer/current (which is not node.js) it works perfectly. So I think I am importing wrong. All I want to do is use that utility function in my app.js
The unPackMessage(val) call doesn't return anything:
module.exports = {
unpackMessage: function(value) {
CCC.CURRENT.unpack(value);
}
}
you need to return CCC.CURRENT.UNPACK(value);
module.exports = {
unpackMessage: function(value) {
return CCC.CURRENT.unpack(value);
}
}
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.
I may be missing something basic as why is it happening.
GET: example.com/users
//gives all data
GET: example.com/users?status=1
//gives data with status = 1
GET: example.com/users // this does not work
gives same data as pervious API condition with status=1
On third hit, self.whereObj is not initialising to default empty object instead it takes previous value of {'status' = '1'}, however self.page and self.limit is taking default value if no query parameter is provided in query string.
example.com/users?limit=3, // takes override to 3 form default value of 5
example.com/users // self.limit takes default 5 and this works fine
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not ?
var Bookshelf = require('../../dbconfig').bookshelf;
Bookshelf.Collection = Bookshelf.Collection.extend({
limit: 5,
page: 1,
whereObj: {}
myFetch: function (query_params,expectedWhereFields) {
var self = this;
var whereObj = self.whereObj ; // this is not initializing
// var whereObj = {}; this is initialising
var page = self.page;
var limit = self.limit; //this is not showing nay initialisation error
for (var x in query_params) {
if (expectedWhereFields.includes(x)) {
whereObj[x] = query_params[x];
}
if (x === 'page') {
page = query_params[x];
}
if (x === 'limit') {
limit = query_params[x];
}
}
var offset = (page - 1) * limit;
function fetch() {
return self.constructor.forge()
.query({where: whereObj})
.query(function (qb) {
qb.offset(offset).limit(limit);
})
.then(function (collection) {
return collection;
})
.catch(function (err) {
return err
});
}
return new fetch();
}
});
module.exports = Bookshelf;
UPDATED
service.js
var Model = require('./../models/Users');
var express = require('express');
var listUsers = function (query_params, callback) {
var expectedWhereFields = ["type", "status", "name"];
Model.Users
.forge()
.myFetch(query_params, expectedWhereFields)
.then(function (collection) {
return callback(null, collection);
})
.catch(function (err) {
return callback(err, null);
});
};
module.exports = {
listUsers: listUsers
};
model/Users.js
var Bookshelf = require('../../dbconfig').bookshelf;
var Base = require('./base');
// Users model
var User = Bookshelf.Model.extend({
tableName: 'user_table'
});
var Users = Bookshelf.Collection.extend({
model: User
});
module.exports = {
User: User,
Users: Users
};
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not?
Because objects are reference values. When you set var whereObj = self.whereObj;, both refer to the same object, and when you copy the query parameters into the object properties you are effectively writing into your defaults instance. This does not happen with primitive values such as strings - they don't have mutable properties.
In an imaginary Session module as bellow, could the _sessData variable be leaked in between request. For instance maybe a user just logged in, and at a "same time" a isAuthed() called is made for a different user. Could this be a problem? This module would be called on every request so I guess it's safe but a confirmation would be great.
module.exports = function(app) {
var _sessData = null;
function Session() {
//
}
Session.prototype.set = function( payload ) {
Cookies.set('session', payload);
_sessData = payload;
}
Session.prototype.isAuthed = function() {
return _sessData && Object.keys(_sessData).length > 0;
}
Session.prototype.clear = function() {
Cookies.set('session', '');
_sessData = {};
}
Object.defineProperty(app.context, 'Session', {
// Not exaclty sure what is happening here with this and _ctx..
// Note: apprently ctx is bound to the middleware when call()ing
get: function() { return new Session(this); }
});
return function * (next) {
var token = Cookies.get('jwt');
if ( ! token ) {
_sessData = {};
return yield* next;
}
try {
_sessData = jwt.verify(token, SECRET);
} catch(e) {
if (e.name === 'TokenExpiredError') {
this.Session.clear();
}
}
yield* next;
}
}
EDIT:
The module get used in a KoaJS app like so (the above module does not produce a proper KoaJS middleware but this is beside the point):
var app = require('koa')();
// JWT session middleware
var session = require("./session")();
app.use(session);
app.listen(3080);
What you are exporting is a function, so _sessData does not actually exist when you import the module. It gets created when you call the function. Each time the function is called -- and it needs to be called once per request -- a new variable in that scope with the name _sessData is created. No, they cannot interfere with each other.