Meteor parsing through a collection setInterval only works once - javascript

So I am trying to check something in a collection many times. On page load everything works great, but when the setInterval kicks in and try's to look over the data a second time it acts like the one peace of data is Null and can't find any info.
Template.something.helpers({
repeatCheck: function repeatCheck() {
setInterval(findTechs, 5000);
console.log("repeatcheck");
}
});
function findTechs() {
_Queue.find({}).forEach(checkTime(this));
};
function checkTime(techInfo) {
console.log(newTime);
console.log(techInfo);
console.log(techInfo.endTime < newTime);
if (techInfo.endTime < newTime) {
console.log("fun");
if (_Queue.findOne({
_id: techInfo._id
})) {
_Queue.remove({
_id: techInfo._id
})
}
}
};

There's an error in your JS.
function findTechs() {
_Queue.find({}).forEach(checkTime(this));
};
This will call checkTime once with the current context as an argument. this probably refers to the window object here. In JavaScript a function call is made when there are brackets behind a variable containing a function. So checkTime(this) calls checkTime and then returns what a call to checkTime will return. Then cursor.forEach is called with that value (which is undefined). So the documents inside the cursor are iterated over with undefined, which does nothing.
What you want to do is something like this:
_Queue.find({}).forEach(checkTime);
Here the actual function behind the checkTime variable is passed to the cursor.forEach call.
You might want to read up on JavaScript callbacks.

Related

Callback can not be invoked properly, if the parameter is a bound function

When a function expects a callback as a param, I suppose it make sense to provide a bound function like this
function invokeCb(cb){
cb();
}
function test(x){
console.log(x)
}
const para="xyz";
invokeCb(test.bind(null,para)) //(1)
invokeCb(()=>{test(para)}) //(2)
I can not see anything wrong with (1). However, when it come to real world, I encounter some unexpected behaviour
Here is a example, in redux
store.subscribe(
()=>{(saveState.bind(null,store.getState()))()}
)
can work while
store.subscribe(saveState.bind(null,store.getState()))
can not correctly, i.e. the store.getState() seems never invoked properly
If you need more context. Here:https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage
Maybe I missed some subtle differences between the two form, can anyone point it out?
The differences are
the time at which store.getState() is evaluated
the return value (by using braces without return, you suppress it)
let data = "abc";
function invokeCb(cb){
data = "xyz";
console.log(cb());
}
function test(x){
console.log(x);
return x.toUpperCase();
}
invokeCb(test.bind(null, data)); // abc ABC
invokeCb(()=>{ test(data); }); // xyz undefined
After some investigation, I figured out the real cause of the bug!
Here is the code to demonstrate:
function invokeCb(cb){
cb();
}
function test(x){
console.log(x)
}
let counter=0;
function getData(){
return ({counter:counter++})
}
const bindVersion=test.bind(null,getData())
const invokeVersion=()=>test(getData())
//first time
invokeCb(bindVersion) //{counter:0}
invokeCb(invokeVersion) //{counter:1}
//second time
invokeCb(test.bind(null,getData())) //{counter:0}
invokeCb(()=>{test(getData())}) //{counter:2}
//third time
invokeCb(test.bind(null,getData())) //{counter:0}
invokeCb(()=>{test(getData())}) //{counter:3}
Explanation:
When using the bind version, the parameter is fixed. i.e. once
it is bound it can not be changed.
One the other hand, when is function is invoke directly, the
parameter is dynamic ,i.e. it can always get the updated data
Conclusion:
NEVER bind dynamic parameter to a function
In my case, case state is immutable in redux, store.getState() return a new reference every time, using bind, it always get the first reference

Add event listener of a method present in another js file

I am accessing few methods written in another js file. So i'm accessing them like this:
file1:
function minit() {
this.addval = function(val1, val2) {
return val1 + val2;
}
function autoexecute(d) {
//do something here//
//raise event//
}
};
file2:
var con = new minit();
var result = con.addval(2, 3);
/*
con.autoexecute(function(d) { //Wanna do something like this
alert(d);
});
*/
Above things are working as expected, getting result..
Now, Suppose autoexecute(d) method is invoking automatically after a time interval. How can i know if the method is executed ?
So that, I want to create an event(in file2) of autoexecute(d)(in file1).
UPDATE:
I hope this example will help you to understand the issue..
company.js //this is the main file which will be used as a reference in ui.html
function hello(personname) { //this method will invoke automatically after 1 minute..
}
ui.html
<script src="company.js"></script>
<script>
$(document).ready(function() {
function bye(personame) { //this method will be called automatically if hello method invoked.... personame is the argument passed from hello method//
alert("comany.js -> hello function is executed");
}
});
</script>
You can only do this if the functions have the same scope (global scope is the best case scenario). If the autoexecute function has local scope then you cannot to do it.
In essence, override the original function like this...
// keep a reference to the original function
var _autoexecute = autoexecute;
// override the original function with your new one
function autoexecute(d) {
alert("before autoexecute"); // fired before the original autoexecute
_autoexecute(d); // call the original autoexecute function
alert("after autoexecute"); // fired after the original autoexecute
}
Now, whenever autotexecute is called it will call your new function which can handle both before and after events, as well as calling the original function. Just remove the (horrible) alerts and replace with event handlers as required.
To my knowledge, and someone should correct me if I am wrong, there is no way (at least without some library) to detect a function being fired in javascript. Function executions do not fire an event that other functions can 'handle' in that that sense.
In your example you wanted a function to automatically fire after the other function has fired, all you need to do is call the function you want to fire at the end of the one that was "fired" in the first place. Confusing but hope this helps.
function handler(){
alert("main function was fired!");
}
function main(){
//Code of main goes here and then at the end just add:
handler();
}
Now when your "main" has finished its work it will call upon the handler function.
Regardless of where you define the handler function, which can be a different file or same file, so long as it is reachable from within the main's scope, it will be fired at the end of it. It can even be declared after main has been declared, so long as it is declared before main is fired.

meteor.js - how to check values from asynchronous callback

CONTEXT
Im making a call which, if successful, changes the value of a boolean from false to true. Then, outside of this call, I check if this boolean is true and, if so, I route to another page.
PROBLEM
Console logs indicate that the if statement which checks the boolean's value is being executed before the calls have had a time to change the boolean's value. I realize that this is because of asynchronicity, but not sure what the correct design pattern for this would be. Here is a snippet:
//set variables to check if the even and user get updated or if error
var eventUpdated = false;
Meteor.call('updateEvent', eventId, eventParams, function(error, result){
if(error){
toastr.error(error.reason)
} else {
var venueId = result;
toastr.success('Event Info Updated');
eventUpdated = true;
console.log(eventUpdated)
}
});
console.log(eventUpdated)
if (eventUpdated) {
Router.go('/get-started/confirmation');
}
POSSIBLE SOLUTIONS
I'm guessing I need a way to hold the if statement from being executed until the callback returns a value. Based on Googling, I think this has something to do with this but not too clear on how to actually use it.
Since the conditional is run before the callbacks have returned a value, you need a conditional that is inside a function that is being run reactively. I used the following code:
Tracker.autorun(function(){
if (Session.get('userUpdated') && Session.get('passwordUpdated') && Session.get('eventUpdated')) {
Router.go('/get-started/confirmation');
}
});
You can read more about Meteor reactivity here.
Nope. The issue is that since it's an async function, this:
console.log(eventUpdated)
if (eventUpdated) {
Router.go('/get-started/confirmation');
}
Runs before the actual call. Use a Session.set inside the call like this:
Session.set("eventUpdated", "true");
And then outside:
eventUpdated = Session.get("eventUpdated");
console.log(eventUpdated)
if (eventUpdated) {
Router.go('/get-started/confirmation');
}
Since Session is a reactive variable you should get the current value correctly.

Retrieve variable from javascript object method callback

In my code I need to call an object method, retrieve the data from its callback, and pass it to another method or function.
someObject.getSomeData({option1:'value1', option2:'value2'},
function(data) {
doAwesomeStuff(data);
}
);
However, the callback does not recognize any functions/objects/variables outside its scope.
What I've tried to do right now is wrap everything around a function.
var myData = '';
(function(myData) {
someObject.getSomeData({option1:'value1', option2:'value2'},
function(data) {
myData = data;
}
);
});
doAwesomeStuff(myData);
However that doesn't work either.
Anybody know how to properly accomplish this?
You haven't really given us enough to go on there, but this statement:
However, the callback does not recognize any functions/objects/variables outside its scope.
...is incorrect. A function has access to everything in scope where it's defined, so for instance:
var a = 10;
function foo(b) {
bar(5);
function bar(c) {
alert(a + b + c);
}
}
foo(12); // alerts "27"
Note how bar had access not only to c, but also to b (from the call to foo) and a (from the outermost scope shown).
So in your example, the anonymous function you're passing in as the callback has access to everything that's in scope where it's defined; doAwesomeStuff having been defined elsewhere presumably has access to different information, so you'll have to have the callback pass it any data it needs.
So I'm guessing your code looks something like this:
function doAwesomeStuff(data) {
// ...
}
function doSomethingNifty() {
var a = 10,
b = 20;
someObject.getSomeData({option1:'value1', option2:'value2'},
function(data) {
doAwesomeStuff(data);
}
);
}
...and you want doAwesomeStuff to have access to a and b from the call to doSomethingNifty. If so, your only options are to pass them into it as arguments (probably best) or export them to variables some scope that doSomethingNifty and doAwesomeStuff share (probably not ideal, too much like globals).
You can bind required variables to the function passed into the async method.
Also, this SO question has a good treatment of the topic.
Your second version is not going to work at all, since you are trying to immediately access the data that are not yet available (not until the callback has been invoked.)
Your first method:
someObject.getSomeData({option1:'value1', option2:'value2'},
function(data) {
doAwesomeStuff(data);
}
);
looks fine. Please provide more details on what is not working.
One problem could be that getSomeData() does not actually call the callback function.
doAwesomeStuff() can modify many different variables from the received data. The variables which can be accessed by doAwesomeStuff() are those that were available to it (in its scope) where it was created..

Javascript: Possible to pass function commands to another function via a variable?

Ok hopefully this come across correctly. I am building a universal javascript function that will build a menu and then also build the functions that each menu item would call. To do this, I need to pass a list of the commands to be called for each option.
So for example:
var thecall = 'alert("hi, this works");';
function myfunction(thecall)
{
//In here I want to excute whatever commands is listed in variable thecall
.....
}
I'm sure doing it this way is completely stupid, but I don't know how else to do this.
Basically, I need my function to perform other functions on a variable basis.
Thanks!!
I made it a bit fancier to show you how you can use it.
var thecall = function(name){alert("hi " + name + ", this works");};
function myFunction(function_ref)
{
function_ref('Mark');
}
myFunction(thecall);
You can execute arbitrary strings of JavaScript using eval(), but that is not the best solution for you here (it's almost never the best solution).
Functions in JavaScript are themselves objects which means you can store multiple references to the same function in multiple variables, or pass function references as parameters, etc. So:
var thecall = function() {
alert("hi, this works");
};
function myfunction(someFunc) {
someFunc(); // call the function that was passed
}
myfunction(thecall); // pass reference to thecall
Note that when passing the reference to the thecall function there are no parentheses, i.e., you say thecall not thecall(): if you said myfunction(thecall()) that would immediately call thecall and pass whatever it returned to myfunction. Without the parentheses it passes a reference to thecall that can then be executed from within myfunction.
In your case where you are talking about a list of menu items where each item should call a particular function you can do something like this:
var menuItems = [];
function addMenuItem(menuText, menuFunction) {
menuItems.push({ "menuText" : menuText, "menuFunction" : menuFunction });
}
function test1() {
// do something
}
addMenuItem("Test 1", test1);
addMenuItem("Test 2", function() { alert("Menu 2"); });
// and to actually call the function associated with a menu item:
menuItems[1].menuFunction();
Notice the second menu item I'm adding has an anonymous function defined right at the point where it is passed as a parameter to addMenuItem().
(Obviously this is an oversimplified example, but I hope you can see how it would work for your real requirement.)
I think your looking for the eval function.
var code= 'alert("hi, this works");';
eval(code);

Categories

Resources