How to store reference to function? - javascript

Given a list of functions, I wish the user to be able to select any of the functions to run at startup. How can this be done so that the user can "save" their choice of function to run the next time the code is run ie what would function runSelectedFunction (below) look like since you can't "save" a javascript function to file? Also, assume the list of potential functions is extensible.
const first = ()=>{
console.log('first');
}
const second = ()=>{
console.log('second');
}
const third = ()=>{
console.log('third');
}
loadUserSelectedFunctionFromDB()
.then(runSelectedFunction)
To be clear, the goal is to persist the user choice even if the code stops executing and is restarted. Normally, this would be done by storing a value in a database but the question is how to store a reference to a function in a database given an extensible set of functions?

Use a map like this:
const m = {
first, second, third
};
let selectFuncName = "first"; // from user selection, maybe click a button
let selectFunc = m[selectFuncName];
loadUserSelectedFunctionFromDB()
.then(runSelectedFunction)

Related

JavaScript/Local Storage

Good Afternoon, I'm hoping for some guidance. I am new to JavaScript and struggling with a project. We have been asked to store new entries into a website application, which once added store into the local storage.
This is what I have so far, but I am at a loss where I am going wrong to get this stored.
The first section surrounded by ** works fine (albeit it doesn't store the entires). It is the last bit where I'm trying to add new code to store the message and invoke the event listener which doesn't work.
Any guidance would be greatly appreciated.
**function addTextEntry(itemKey, initialText, isNewEntry) {
// Create a text element to edit the entry
var textElement = document.createElement("textarea");
textElement.rows = 5;
textElement.placeholder = "(new entry)";
// Set the textarea's value to the given text (if any)
textElement.value = initialText;
// Add a section to the page containing the textarea
addSection(itemKey, textElement);
// If this is a new entry (added by the user clicking a button)
// move the focus to the textarea to encourage typing
if (isNewEntry) {
textElement.focus();
}**
// Create an event listener to save the entry when it changes
function saveEntry() {
// A new version of this function is created every time addTextEntry is called,
// so it can access all the variables available in this call to addTextEntry
console.log("saveEntry called with variables in scope:", {
itemKey,
initialText,
isNewEntry,
textElement,
});
document.getElementById(initialText);
item = makeTextItem(initialText);
localStorage.setItem(itemKey);
textElement.addEventListener("initialText", saveEntry);
}
}
setItem method takes 2 parameters:
keyName: The name of the key in the Local Storage
keyValue: The value for a given key
In you code, you are passing only one parameter itemKey. You should also pass the value for that key as a second parameter.
document.getElementById(initialText);
This statement doesn't do anything with the result. You may want to assign it to a value like const textElement = document.getElementById(initialText);
item = makeTextItem(initialText);
You are missing the code for makeTextItem but that's still irrelevant since item isn't being used anywhere in the code below it.
localStorage.setItem(itemKey);
setItem takes TWO params, the key and the thing you want to save storage.setItem(keyName, keyValue);
textElement.addEventListener("initialText", saveEntry);
addEventListener's first argument should be a valid event. addEventListener(type, listener);

A way to add parameters to variables or something so I don't spam functions and vars

So the point of this, game like, website JavaScript is creating triggers. The Const pgUnlock is the on and off switch. I want it so that when the viewer clicks on a button, I will change the element to turn the false into a true. For example, below, it checks if the number 1 is in the [0] index and if it is, it'll unlock a new part of the website, by replacing the # with the next page link. The function 'alertbox()' checks this and if the trigger isn't on, it'll make a button visible, letting the player know that the "page is locked". So my question is how do I add parameters to consolidate the code so I'm not creating 5 more 'alertbox()' functions because the 'check' var has to be customized for each placement for 'pgUnlock'. If not, I'm fine with repeating the code, I just want to see if I/we can keep everything performance friendly by using cleaner code, as I'm not that familiar with JavaScript. To let you know how dumb I am, one of my tries was: 'var check(x,y)= pgUnlock.includes(x,y);'
var a = document.querySelector('.rebtn[href="#"]');
const pgUnlock= [0,0,0,0,0];
var check= pgUnlock.includes(1,0);
var check2= pgUnlock.includes(2,0);
var check3= pgUnlock.includes(3,0);
var check4= pgUnlock.includes(4,0);
var check5= pgUnlock.includes(5,0);
if (check==true) {
a.setAttribute('href', './introPage.html');
}
reBtn.onclick=()=>{
alertbox();
}
legBtn.onclick=()=>{
alertbox();
}
godBtn.onclick=()=>{
alertbox();
}
chgBtn.onclick=()=>{
alertbox();
}
ch2Btn.onclick=()=>{
alertbox();
}
function alertbox(){
if(check==false){
alertBtn.classList.add("visalert");
}
}

Javascript AlgoliaJS .clearCache() on empty search results is always a "search behind"

I have a function that is executed each time a user updates an entry, in order to keep the list of entries up-to-date. The problem I'm running into is that when I run .clearCache() on the index, even though I'm doing it before the actual search function is run, it takes two reloads in order to get the latest updates. It's acting as if it's a reload behind. I have no idea what's causing this, but here is my search function:
search() {
this.results = [];
// Clear the algolia cache
this.auditionsIndex.clearCache();
this.auditionsIndex.search('', options).then(result => {
if(result.hits && result.hits.length > 0) {
this.results = result.hits;
}
// Clear the cache one more time
this.auditionsIndex.clearCache();
});
}
Changing something in an Algolia index happens asynchronously, when you execute something like index.saveObject() the result of the Promise/callback will be an object with taskId. You can then index.waitTask for that task, and send some event to your frontend to let it know to clear the cache and search.
see https://www.algolia.com/doc/api-reference/api-methods/wait-task/#methods

Firebase functions - adding new value to the oldvalue

I'm creating an android app that logs how long a person spends on certain things. I want to add the time spent to the total time spend, so I know how long a user has spent on an exercise type
I want to do it in a function, since I think it's easier than transactions.
exports.addExerciseTime = functions.database.ref('users/{userid}/stats/exerciseTime/{type}').onWrite( event =>{
console.log("Exercise time updates...");
var newdata = event.data.val();
var oldData = event.data.previous.val();
return event.data.ref.update(oldData+ newdata);
});
Now, I know that this function will loop until firebase shuts it down.
But how would I do this? Is there an easier way to do this?
you have an easy option of adding a flag indicating that you updated the data. next time you will get into the function, just start by checking if the flag exists in if so, exit the function. the con of this one is that you will run the function at least n+1
another option, according to their latest post, you know have a "onUpdate" and "onCreate" triggers as well. you might be able to use them smartly to optimize this even more (for example: only on first creation do XYZ, so it won't run on each update).
https://firebase.googleblog.com/2017/07/cloud-functions-realtime-database.html
Like you are saying, onWrite will capture every writing event. My solution would be replacing onWrite with onCreate, however let the user write to another path because Firebase will keep triggering the function. Besides that, your approach this is not the best solution since the updates can conflict. The use of transactions is better. That would look like this:
exports.addExerciseTime = functions.database.ref('users/{userid}/stats/exerciseTime/{type}').onCreate( event =>{
console.log("Exercise time updates...");
var newdata = event.data.val();
const pathToValue = //create the path here to exercisetime
return pathToValue.transaction(function(exercisetime) {
return (exercisetime || 0) + newdata;
});
});
*Notice the onCreate event instead of onWrite. Again: You will need to write it to a other path.

node.js setInterval not working in custom module

I am developing a web application in node.js to collect data from devices on a network using snmp. This is my first real encounter with node.js and javascript. In the app each device will be manipulated through a module I named SnmpMonitor.js. This module will maintain basic device data as well as the snmp and database connection.
One of the features of the app is the ability to constantly monitor data from smart metering devices. To do this I created the following code to start and stop the monitoring of the device. It uses setInterval to constantly send a snmp get request to the device. Then the event listener picks it up and will add the collected data to a database. Right now the listener just prints to show it was successful.
var dataOIDs = ["1.3.6.1.2.1.1.1.0","1.3.6.1.2.1.1.2.0"];
var intervalDuration = 500;
var monitorIntervalID;
var dataCollectionEvent = "dataCollectionComplete";
var emitter = events.EventEmitter(); // Uses native Event Module
//...
function startMonitor(){
if(monitorIntervalID !== undefined){
console.log("Device monitor has already started");
} else {
monitorIntervalID = setInterval(getSnmp,intervalDuration,dataOIDs,dataCollectionEvent);
emitter.on(dataCollectionEvent,dataCallback);
}
}
function dataCallback(recievedData){
// receivedData is returned from getSnmp completion event
// TODO put data in database
console.log("Event happened");
}
function stopMonitor(){
if(monitorIntervalID !== undefined){
clearInterval(monitorIntervalID);
emitter.removeListener(dataCollectionEvent,dataCallback);
} else {
console.log("Must start collecting data before it can be stopped");
}
}
//...
I also have a test file, test.js, that requires the module, starts monitoring, waits 10 seconds, then stops it.
var test = require("./SnmpMonitor");
test.startMonitor();
setTimeout(test.stopMonitor,10000);
My problem is that the setInterval function in startMonitor() is not being run. I have tried placing console.log("test"); before, inside, and after it to test it. The inside test output never executes. The monitorIntervalID variable is also returned as undefined. I have tested setInterval(function(){ console.log("test"); },500); in my test.js file and it runs fine with no issues. I feel like this is a noobie mistake but I just can't seem to figure out why it won't execute.
Here is a link to the entire module: SnmpMonitor.js
I not sure exactly what was wrong but I got it to work by overhauling the whole class/module. I thought the way I had it was going to allow me to create new monitors objects but I was wrong. Instead I created two functions inside the monitor file that do the same thing. I changed the start function to the following.
SnmpMonitor.prototype.start = function() {
var snmpSession = new SNMP(this.deviceInfo.ipaddress,this.emitter);
var oids = this.deviceInfo.oids;
var emit = this.emitter;
var duration = this.intervalDuration;
this.intervalID = setInterval(function(){
snmpSession.get(dataCollectionEvent,emit,oids);
},duration);
};
The setInterval function seems to work best when the callback function is set inside an anonymous function, even though technically you can pass it directly. Using the this. notation I created some class/module/function variables (whatever its called in js) that are in scope of the whole class. For some reason the variables accessed through this. do not work so well when directly in a function or expression so I created temp variables for them. In my other version all the variables were global and js doesn't seem to like that.

Categories

Resources