I'm sorry if this is a horrible question, I'm a beginner to JS.
So what I'm trying to do is have a function that runs right away and then that function will run other functions if a certain thing is true.
But, when I run it, it says that the function is not yet defined and I can't figure out how to solve this problem. I thank you for your time.
function start() {
var start = prompt('Yes or no?');
if (start === 'Yes') {
yes();
}
but because its in the beginning the functions it runs are below it and are not able to run.
//declare a function called yes
var yes = function(){
alert('You said yes');
};
function start() {
var start = prompt('Yes or no?');
if (start === 'Yes') {
yes();
}
}
start(); //call first function
Passing function as a parameter example.
var fun1 = function(callback) {
var res = prompt('Your ans please');
callback(res);//pass response to function.
};
var handleRes = function(res){
if (res==='yes'){
alert('you said yes');
}
else if(res==='no'){
alert('you said no');
}
else {
alert('you did not say yes or no');
}
};
//call fun1 pass handleRes function to it for callback
fun1(handleRes);
Order in which you write your function matters in JavaScript in some scenarios. Probably the function you are calling is written below it.
Related
I'm Using the code below to let my function A only be triggered 3 times.
as I'm new to Javascript I think maybe you guys could show me a better way.
var num = 0;
if(num<4){
function A() {
num++
}
}
I'd put the num check inside the function, in case you want to call it anywhere else it will check your num record when you call it instead of having it automatically run 3 times when you start your program.
var num = 0;
function A() {
if(num<4){
//perform whatever you want your func to do
num++;
} else {
console.log("You performed this function 3 times already");
}
}
This depends highly on what you want to achieve, but one way is using recursion:
function foo(param1, param2, count = 3) {
if (count > 0) {
// ... some code ...
return foo(param1, param2, count-1)
}
return null; // just as example and check for the null later
}
Is it possible to pass a callback function that does not exist yet? My goal is to have a common function that will wait for another callback function to exist, when it does exist, it should execute it. This is what I have so far, but I can't figure out how to pass the function in that doesn't exist as a function yet.
function RunTemplateFunction(callback, userInfo) {
if ($.isFunction(callback)) {
callback(userInfo);
} else {
var myInterval = setInterval(function () {
if ($.isFunction(callback)) {
clearInterval(myInterval);
callback(userInfo);
}
}, 200);
}
}
I run the function like this:
RunTemplateFunction(MyFunctionToRun, GetUserInfo());
I get MyFunctionToRun is undefined for obvious reasons, I also tried the workaround of passing the function as a string and then convert the string to a function using eval(). But that throws the same error. I also thought of using the new function(), but that actually creates a new function.
Any help is appreciated. thank you.
If you call RunTemplateFunction by undefined there is no way we can see, is callback is defined or not, as we don't have reference to anything.
If you can modify the declaration to accept object as below, we can achieve what we want
function RunTemplateFunction(options, userInfo) {
if ($.isFunction(options.callback)) {
console.log('called1',userInfo);
options.callback(userInfo);
} else {
var myInterval = setInterval(function () {
if ($.isFunction(options.callback)) {
console.log('Called dynamically!!');
clearInterval(myInterval);
options.callback(userInfo);
}
}, 200);
}
}
var options = {}
RunTemplateFunction(options,{user:122});
options.callback = function(){
console.log("I'm called!!");
}
This will print
Called dynamically!!
I'm called!!
EDIT:
We can also call callback function in following way without setInterval, it will look different but options.callback variable is replaced by template.callMe function and its instantaneous also.
function TemplateRunner(userInfo){
this.callMe = function(cb){
this.templateFunction(cb);
}
this.templateFunction = function(callback){
callback(userInfo);
}
}
var template = new TemplateRunner({user:100})
template.callMe(function(user){
console.log('call me1',user);
});
template.callMe(function(user){
console.log('call me2',user);
})
This will print
call me1 {user: 100}
call me2 {user: 100}
I have two function like below:
var doSomething = function() {
// first check if user wants to proceed and some other restrictions
checkIfReallyShouldProceed();
console.log('ok, proceed');
// proceed and do something
}
var checkIfReallyShouldProceed = function() {
var check = confirm('really proceed?');
if(!check){
//stop executing doSomething
}
}
doSomething();
If the user does not confirm I want to return from doSomething. Of course I could return the result of the check variable to doSomething and have something like
if(!checkIfReallyShouldProceed()){
return;
}
there, but I want the called function to stop the calling function from executing. Is this possible and if so, how?
An if condition is made for this type of conditional procedure:
var doSomething = function() {
if (checkIfReallyShouldProceed()){
return true; // This will stop the doSomething function from executing
}
console.log('ok, proceed');
}
var checkIfReallyShouldProceed = function() {
return confirm('really proceed?'); // returns true/false
}
doSomething();
In the checkIfReallyShouldProceed function, return whether or not the user wants to proceed. In doSomething, it will stop executing if the called method returns true
Here in result() method, whenever it comes to else part, I need to get out of the function callthis().
It should not execute kumar() function.
Is this possible?
Actually, I can use like this
if(result) //if this method is true, it will come inside
{
kumar();
}
But this is not I want. while returning false from result() method, it should get out of the loop function calthis()
function calthis()
{
var i=1;
if(i==0)
{
alert("inside if");
}
else
{
alert("inside else");
result();
kumar();
}
}
function result()
{
var res = confirm("are you wish to continue");
if(res==true)
{
return true;
alert("inside if result");
}
else
{
return false;
}
}
function kumar()
{
alert("inside kumar");
}
Click here
There's a bunch wrong here.
First, if (result) just tests whether the variable result contains a truthy value, it doesn't actually invoke the function. If you want to test the return value of the function, you need
if (result()) {
Secondly, you're not understanding that return immediately leaves the current function. You can't meaningfully do this:
if(res==true)
{
return true;
alert("inside if result");
}
That alert cannot be reached. The function returns immediately when return true is encountered.
Thirdly, to exit callThis early, you simply need to return early. It's up to the function callThis to conditionally return; you cannot force a return from down inside the result function. A function cannot forcibly return out if the context that called it. It's not up to the internals of the result function to determine if kumar should run. You cannot influence the path of execution in the calling method directly. All result can do is return something, or (needlessly complex in this case) accept a callback and conditionally execute it.
Just return from callThis if the result of result() is false:
function calthis()
{
var i=1;
if(i==0)
{
alert("inside if");
}
else
{
alert("inside else");
if (!result()) return;
kumar();
}
}
To exit any function simply use return;
However it seems like you want to call a function if the user clicks confirm, is that correct? If so:
var res = confirm("are you wish to continue");
if (res === true)
{
kumar();
}
If you want to call a function if the user does not click confirm:
var res = confirm("are you wish to continue");
if (!res)
{
kumar();
}
You got a lot of confusing code going on there, but if the idea is to stop a function, simply use "return false;" and the code execution stops
I want call few function one after another recursively with setTimeout.
var flag = 0 ;
function slave1(){
if(flag < 60) {
var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT1"); // Checking if DOM has loaded or not. If yes then doing something.
if (COPY_PO_LINE_DIV != null) {
flag = 0;
//doing something
} else {
setTimeout(slave1,2000); //waiting for 2 seconds and checking again.
}
}
}
//doing similar task
function slave2(){
if(flag < 60) {
var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT2");
if (COPY_PO_LINE_DIV != null) {
flag = 0;
//doing something
} else {
setTimeout(slave2,2000);
}
}
}
function master() {
slave1();
console.log("Without completing slave1 function.");
slave2();
}
Through master() function I want to call multiple functions one after another, however in current situation its calling slave2() without completing slave1(). How can I make sure that slave1() has executed completed. If DOM element is not loaded than it should execute 60 times after every 2 seconds and than it should come out from slave1() and go to next one.
I want to execute same function for 60 times if dom element is not loaded without returning the control to next function.
You need to adjust slave1 to run a callback when it is finished which will be slave2.
function slave1(callback){
if(flag < 60) {
var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT1"); // Checking if DOM has loaded or not. If yes then doing something.
if (COPY_PO_LINE_DIV != null) {
flag = 0;
//doing something
callback();
} else {
setTimeout(slave1,2000); //waiting for 2 seconds and checking again.
}
}
}
function slave2(){...}
function master() {
slave1(slave2);
console.log("Without completing slave1 function.");
}
This is your basic javascript chaining. If you have more slaves you might want to look into async.series otherwise you go into callback hell as Gabs00 has put it nicely:
slave1(function(){
slave2(function(){
slave3(function(){
slave4(slave5);
});
});
});
If you need to pass values to callbacks then you need to use an intermediate anonymous function which in turn calls the intended callback with the arguments in question. To do that, you need define your functions so that they use the arguments:
function slave1(str, callback){...}
function slave3(i, callback){...}
slave1("some argument", function(){
slave2("another argument", function(){
slave3(1, function(){
slave4(2, slave5);
});
});
});
Consider using promises for things like that. Here an implementation on top of jQuery, other promise libraries work similarly.
function waitForElement(elementId, maxTries, checkInterval) {
var d = $.Deferred(), intvalID, checkFunc;
// set up default values
maxTries = maxTries || 60;
checkInterval = checkInterval || 2000;
checkFunc = function () {
var elem = document.getElementById(elementId);
if (maxTries-- > 0 && elem) {
clearInterval(intvalID);
d.resolve(elem);
}
if (maxTries <= 0) {
clearInterval(intvalID);
d.reject(elementId);
}
};
// set up periodic check & do first check right-away
intvalID = setInterval(checkFunc, checkInterval);
checkFunc();
return d.promise();
}
Now, if you want to test for elements one after another, you can cascade the calls like this:
function master() {
waitForElement("DOM_ELEMENT1").done(function (elem1) {
waitForElement("DOM_ELEMENT2").done(function (elem2) {
alert("elem1 and elem2 exist!");
// now do something with elem1 and elem2
}).fail(function () {
alert("elem1 exists, but elem2 was not found.");
});
}).fail(function () {
alert("elem1 not found.");
});
}
or you can do it in parallel and have a callback called when all of the elements exist:
function master() {
$.when(
waitForElement("DOM_ELEMENT1"),
waitForElement("DOM_ELEMENT2")
)
.done(function (elem1, elem2) {
alert("elem1 and elem2 exist!");
// now do something with elem1 and elem2
})
.fail(function () {
alert("not all elements were found before the timeout");
});
}
Your slave2 function should be passed to slave1 function as a callback and should be called in slave1 after it finishes (if ever?). Your current situation is quite common, since setTimeout() function is asynchronous, thus JS interpreter doesn't wait till the function is completed, but sets the setTimeout() result at the end of the Evet Loop and continues processing the master() method.
In order to pass arguments to functions, creating anonymous functions turns out to be an overkill. Consider using "bind" instead. So, if you've got
function slave1(str, callback){...}
function slave2(str, callback){...}
function slave3(i, callback){...}
function slave4(i, callback){...}
function slave5()
Instead of using
slave1("some argument", function(){
slave2("another argument", function(){
slave3(1, function(){
slave4(2, slave5);
});
});
});
Consider using
slave1("some argument",
slave2.bind(null, "another argument",
slave3.bind(null, 1,
slave4.bind(null, 2, slave5)
)
)
);
Much easier, more efficient in terms of memory and CPU utilization.
Now, how to do this with setTimeout:
slave1("some argument",
setTimeout.bind(null, slave2.bind(null, "another argument",
setTimeout.bind(null, slave3.bind(null, 1,
setTimeout.bind(null, slave4.bind(null, 2,
setTimeout.bind(null, slave5, 0)
),0)
),0)
),0)
);
I explained the problem in more detail at
http://morethanslightly.com/index.php/2014/09/executables-the-standard-solution-aka-mind-the-bind/