I have some ambiguity in Javascript callback functions.
The first code is structured as follows:
function firstFunction()
{
var message = "something";
secondFunction(message);
}
function secondFunction(message)
{
var myButton = document.getElementById("my-button");
myButton.addEventListener('click',thirdFunction(message));
}
function thirdFunction(message)
{
console.log("the messages is: "+message);
}
When I run the script above, the thirdFunction gets executed without clicking the button.
After some research, I read about the closure in Javascript. Then I changed the code to the following structure:
function firstFunction()
{
var message = "something";
secondFunction(message);
}
function secondFunction(message)
{
var myButton = document.getElementById("my-button");
myButton.addEventListener('click',thirdFunction);
}
function thirdFunction(message)
{
return function(){
console.log("the messages is: "+message);
}
}
I got the expected result. The thirdFunction is executed only when the button is clicked.
I am not sure if I my second code structure is correct? I am not sure if I'm getting the closure concept correctly as I never returned a function in conventional programming before. This is a new concept to me. Please, correct me if I'm wrong.
EDIT:
Some of the solutions suggest writing it like this:
myButton.addEventListener('click', function() { thirdFunction(message) });
For code readability, I am trying to avoid this. I prefer to place the code for the thirdFunction outside the secondFunction.
Use an anonymous function to make the closure in the correct environment:
function secondFunction(message)
{
var myButton = document.getElementById("my-button");
myButton.addEventListener('click', function() {
thirdFunction(message)
});
}
Related
I am trying to understand how this code works. I finally figured out it is a loop. It is not a "while" or "for" loop, but it is a loop nonetheless by virtue of calling itself I think (please correct me if I am wrong).
I understand it's main function: to pass JQuery when it is loaded to my 'foo' function, when ever jQuery has loaded. To do that it checks for jQuery in Window and if not there it resets the timer(). That is the loop. I get that.
Let me explain what I do not understand:
the call: CheckDependency.Deferred.execute(foo);
why the "Deferred" keyword?
execute baffles me: I expect that if I call CheckDependency.Deferred.execute that it would only execute that method. Why does it obviously run the timer function. why could it not simply have that code after the timer() since it keeps looping there and then return jquery?
Speaking of return. Why is there a method in there? CheckDependency.Deferred.execute(foo); is as crazy to me as CheckDependency.Deferred.RETURN.execute(foo); (or some similar crazy statement)
I am fairly new to JavaScript (from PHP). Here the code:
function foo(){ console.log('jQuery found!');
}
var CheckDependency = CheckDependency || { };
CheckDependency.Deferred = function ()
{
var functions = [];
var timer = function() {
if (window.jQuery) {/* && window.jQuery.ui*/
while (functions.length) {
functions.shift()(window.jQuery);
}
} else {
window.setTimeout(timer, 250);
}
};
timer();
return {
execute: function(onJQueryReady)
{
if (window.jQuery) { // && window.jQuery.ui
onJQueryReady(window.jQuery);
} else {
functions.push(onJQueryReady);
}
}
};
}();
CheckDependency.Deferred.execute(foo);
Let me start by saying I'm not a javascript expert, but I dabble :) I'll take a stab at describing what is going on here.
First, This creates a new object called "CheckDependency".
var CheckDependency = CheckDependency || { };
Next, it runs an anonymous function, and stores the result in CheckDependency.Deferred.
CheckDependency.Deferred = function ()
{
.
.
.
.
}()
The anonymous function runs the following code:
var functions = [];
var timer = function() {
if (window.jQuery) {/* && window.jQuery.ui*/
while (functions.length) {
functions.shift()(window.jQuery);
}
} else {
window.setTimeout(timer, 250);
}
};
timer();
The last part of the function code returns a new function execute, which gives CheckDependency.Deferred a function execute.
return {
execute: function(onJQueryReady)
{
if (window.jQuery) { // && window.jQuery.ui
onJQueryReady(window.jQuery);
} else {
functions.push(onJQueryReady);
}
}
};
Finally, this new function is called
CheckDependency.Deferred.execute(foo);
The final result of this is that the code starts a background timer that calls itself until window.jQuery is true - which means jQuery is loaded. Then, the function passed to execute is passed into this loop and so will once jQuery is available, the original function passed to "execute" will be called with the instance of window.jQuery.
I hope I did this justice, and I hope my answer helps! Please let me know if you have any question.
I want to inject a JavaScript function into DOM and call it at a later time.
Something like this
var funcCode = 'function test() { alert("test"); }';
function callFunc(functionName){
functionName();
}
callFunc('test');
How can I do this?
Update
Contextual problem
I have actions and function in the database.
Functions are based on actions.
I retrieve both actions and functions, and show actions on UI but I need to inject the JS function for each action shown. If an action is dismissed so the function should be.
DOM functions needed
var name1 = function () {
return {
run : function() {
// code for action 1
}
}
}
var name2 = function () {
return {
run : function() {
// code for action 2
}
}
}
...
Manager for actions (and want something like this)
Manager.Use(funcName) => to call run
If you're needing to inject a function as a string into the DOM, and then execute it, you're probably doing something wrong.
That said, here's one way you could do it. I can't make a fiddle 'cos they (rightly) don't let you inject script tags into the HTML.
var funcCode = 'function test() { alert("test"); }';
$('body').append('<script type="text/javascript">'+funcCode+'</script>');
function callFunc(functionName){
eval(functionName)();
}
callFunc('test');
Note - the code above will do what you ask, but I implore you to revisit your deisgn, and look at why you're trying to do this. It's probably not right.
var dynamicCode = "var name1 = function () {return {run: function () {alert('1')}}}; var name2 = function () {return {run: function () {alert(2)}}};";
eval(dynamicCode);
function use (funcName) {
eval(funcName + "()['run']()");
}
use("name2");
Here is my issue, I have a javascript function in a .js file that performs some actions, gathers information, and uses a callback. The callback function is also a javascript function but resides in a .cshtml file. I am have difficulties returning a value from my .js javascript function to my .cshml javascript callback function.
Here is a little sample code...
my .js function which I would like to return a value from:
function returnVal(itemID, onCompleteCallback) {
//get vals from DB
onCompleteCallback();
}
my .cshtml script that calls the previous function and I need to get the returned value is a button click even:
updateBtn.onclick = function(e) {
if(action==1) {
returnVal(itemID, OnCompleted);
}
I have tried 2 methods, neither has worked. I have tried returning a value within the "returnVal" function which doesn't seem to results in anything being returned. I have also tried passing a variable as type var and setting it within the returnVal function, it was my understanding that primitives are passed by value (and thus this wouldn't work) but objects are passed by reference and so I thought this would work. At any rate, neither was successful. Bellow are examples of how I have tried the aforementioned 2 methods:
Method 1:
function returnVal(itemID, onCompleteCallback) {
//get vals from DB
onCompleteCallback();
return x;
}
updateBtn.onclick = function(e) {
if(action==1) {
x = returnVal(itemID, OnCompleted);
}
}
Method 2:
function returnVal(x, itemID, onCompleteCallback) {
//get vals from DB
onCompleteCallback();
}
updateBtn.onclick = function(e) {
if(action==1) {
var x;
returnVal(x, itemID, OnCompleted);
}
}
In both cases 'x' is not set. I hope I have provided enough details, any help would be greatly appreciated.
I think you want something like
function returnVal(itemId, onComplete){
var data = getValueFromDatabase();
onComplete(data);
}
updateBtn.onclick = function(e) {
if(action==1) {
returnVal(itemID, function(data){
// Do something with returned value i.e. 'data'
});
}
}
I don't know why my function in the console shows not defined. I have tried to make it right and I just can't seem to get it. It works fine until I try to use the setInterval function. Also the build keeps saying I am missing a semicolon, but I just don't see it.
$(document).ready(function () {
var machineDataViewModel = {
machineDataItems: ko.observableArray([]),
loadMachineDataItems: function DataLoad() {
machineDataViewModel.machineDataItems.length = 0;
$.getJSON("http://localhost/JsonRestful/Service1.svc/GetMachineData", function (data) {
$.each(data.GetMachineDataResult, function (index, item) {
machineDataViewModel.machineDataItems.push(new machineDataModel(item));
});
});
}
};
ko.applyBindings(machineDataViewModel);
machineDataViewModel.loadMachineDataItems();
setInterval(DataLoad, 9000);
});
function machineDataModel(item) {
this.mach_no = ko.observable(item.mach_no),
this.VAR1 = ko.observable(item.VAR1),
this.VAR2 = ko.observable(item.VAR2),
this.VAR3 = ko.observable(item.VAR3),
this.VAR4 = ko.observable(item.VAR4)
};
You can't define the DataLoad() function the way you are and expect it to be available in your setInterval(). It simply doesn't work that way. The symbol DataLoad is only available inside the scope of that function. Instead, you can call it as:
setInterval(machineDataViewModel.loadMachineDataItems, 9000);
Here's a simple demonstration that shows you can't name your function like you are and expect to use that name outside that scope: http://jsfiddle.net/jfriend00/6t0pp60s/ (look in the debug console to see the error).
FYI, if you need your function to have the right value of this (which I don't think you actually do), then you would call it like this (with a semi-colon at the end of every line):
setInterval(machineDataViewModel.loadMachineDataItems.bind(machineDataViewModel), 9000);
As for the semicolon issue, jsHint points to the this.VAR4 assignment line. I'd suggest changing machineDataModel() to this (which gives you a clean bill of health in jsHint):
function machineDataModel(item) {
this.mach_no = ko.observable(item.mach_no);
this.VAR1 = ko.observable(item.VAR1);
this.VAR2 = ko.observable(item.VAR2);
this.VAR3 = ko.observable(item.VAR3);
this.VAR4 = ko.observable(item.VAR4);
}
I am new to javascript and have a quick question. Say i have the following code:
function entryPoint()
{
callFunction(parameter);
}
function callFunction(parameter)
{
... //do something here
var anotherFunction = function () { isRun(true); };
}
My question is that when callFunction(parameter) is called, and the variable anotherFunction is declared, does isRun(true) actually execute during this instantiation? I am thinking it doesnt and the contents of the anotherFunction are only "stored" in the variable to be actually executed line by line when, somewhere down the line, the call anotherFunction() is made. Can anyone please clarify the function confusion?
It seems the confusion is this line of code
var anotherFunction = function () { isRun(true); };
This declares a variable of a function / lambda type. The lambda is declared it is not run. The code inside of it will not execute until you invoke it via the variable
anotherFunction(); // Now it runs
You almost described it perfectly.
anotherFunction just receives a reference to a newly created Function Object (yes, Functions are also Objects in this language) but it does not get executed.
You could execute it by calling
anotherFunction();
for instance.
You can write a simple test like so:
entryPoint();
function entryPoint()
{
alert("In entryPoint");
callFunction();
}
function callFunction()
{
alert("In callFunction");
var anotherFunction = function () { isRun(); };
}
function isRun()
{
alert("In isRun");
}
And, the answer is no, isRun() does not get called.