I'd like to stop returning to the first function. Look at my example for better understanding:
function function1() {
function2();
console.log('back after called function'); // shoudn't log if condition is true
}
function function2() {
if (condition === true) { // if condition is true, stop right here (no callback to function1)
return false;
} else {
// callback is allowed
}
}
Use a ternary operator.
function2() ? false : console.log('back after called function');
You can add more lines in as well - use an IIFE.
function2() ? false : (() => {
console.log('back after called function');
//More code
})();
I think it is impossible for function2 not to return to function1
function function1() {
if (function2()) return;
console.log('back after called function'); // shoudn't log if condition is true
}
Simple Just throw and caught the error
function function1() {
try{
function2();
console.log('back after called function'); // shoudn't log if condition is true
}catch(e){
console.log(e.message);
}
}
function function2() {
if (1 === 1) { // if condition is true, stop right here (no callback to function1)
throw new Error('forced stopped');
} else {
// callback is allowed
}
}
<!DOCTYPE html>
<html>
<body onLoad="function1()">
</body>
</html>
The simplest way should be something like:
function function1() {
if (function2()) {
console.log('back after called function');
}
}
As Jack Bashford suggested (but wrote in the wrong way), you could use the ternary operator:
function function1() {
function2()? console.log('back after called function') : return;
}
Or, for a more complex code process, you could use a callback function:
function function1() {
function2(function(error) {
if (!error) {
console.log('back after called function');
}
});
}
function function2(callback) {
if (condition === true) {
callback("Error: condition false");
} else {
callback(null);
}
}
EDIT:
Using my last option you can do exactly what you asked: do not return to function1:
function function1() {
function2(function() {
console.log('back after called function');
});
}
function function2(callback) {
if (condition === true) {
return;
} else {
callback();
}
}
But I think for the sake of good practice you should always call the callback.
Related
I am was looking into javaScript best practices for clean and optimised code, and I'm not sure about what is the best approach for my situation. I edited my code for clarity and it contains dummy code.
Writing Nested Functions
I want to do something after the page has loaded, so I have written some code that executes after page load. So I have defined all the functions inside this load function. It's working perfectly.
window.addEventListener('load', function() {
var conditionOne = true;
if(conditionOne) {
firstFunction();
}
function firstFunction() {
console.log('running first function');
secondFunction();
}
function secondFunction() {
console.log('running second function');
}
//
//
//
function tenthFunction() {
console.log('running tenth function');
}
});
Alternative way would be like this:
window.addEventListener('load', function() {
var conditionOne = true;
if(conditionOne) {
firstFunction();
}
});
function firstFunction() {
console.log('running first function');
secondFunction();
}
function secondFunction() {
console.log('running second function');
}
//
//
//
function tenthFunction() {
console.log('running tenth function');
}
This surely is more cleaner as the functions are separated and they are only invoked in the after load listener event. Does this also have any performance optimisation. I believe the second one is the most optimised in this scenario. Please correct me if there are any other better ways.
Conditional check before executing function.
Suppose that I need to have conditional check before executing the function, I thought of 2 ways of doing it.
First
function mainFunction() {
if(conditionOne) {
firstFunction();
}
secondFunction();
if(conditionThree) {
thirdFunction();
}
}
function firstFunction() {
console.log('running first function');
}
function secondFunction() {
console.log('running second function');
}
function thirdFunction() {
console.log('running first function');
}
Second
function mainFunction() {
firstFunction();
secondFunction();
thirdFunction();
}
function firstFunction() {
if(conditionOne) {
console.log('running first function');
}
}
function secondFunction() {
console.log('running second function');
}
function thirdFunction() {
if(conditionThree) {
console.log('running first function');
}
}
Second one looks like clean code, but I am not sure if its costly, Can anyone suggest which would be a better and optimised way.
I'm trying to create a function that's responsible for checking a boolean and exiting early with a warning, if true.
Here's example of what i'm trying to achieve:
function warnAndDie(shouldDie) {
if(shouldDie) {
console.log("go away, i'm dying!");
// TODO: some code to cause the calling function to exit early
}
}
function triggerTheWarnAndDie() {
shouldWarnAndDie(true);
console.log("I should never run!");
}
function dontTriggerTheWarnAndDie() {
shouldWarnAndDie(false);
console.log("I should run!");
}
What can i do so that warnAndDie is able to cause the calling functions to terminate early?
thank you
You have several options. I'll list the two very basic ones for you:
Return a value (probably boolean) and return early from you caller depending on the initial return value
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
console.log("go away, i'm dying!");
return true;
}
return false;
}
function triggerTheWarnAndDie() {
var hasDied = shouldWarnAndDie(true);
if (hasDied) return;
console.log("I should never run!");
}
Throw an exception
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
throw "Go away, i'm dying!";
// or cleaner:
// throw new dyingException("Go away, i'm dying!");
}
}
function triggerTheWarnAndDie() {
try {
shouldWarnAndDie(true);
console.log("I should never run!");
}
catch(err) {
console.log(err+" He's dead Jim!");
}
}
There are more advance mechanics which are probably out of scope for you right now, but LINQ's nice answer about callbacks and promises is definitely worth a look.
This can be achieved with basic exception handling. Here I have created a custom exception which can be caught using a try catch statement.
function shouldWarnAndDie(shouldDie) {
if(shouldDie) {
throw new DyingException();
}
}
function triggerTheWarnAndDie() {
try {
shouldWarnAndDie(true);
} catch(err) {
console.log(err.message);
return;
}
console.log("I should never run!");
}
function dontTriggerTheWarnAndDie() {
try {
shouldWarnAndDie(false);
} catch(err) {
console.log(err.message);
return;
}
console.log("I should run!");
}
// custom Exception handler
function DyingException() {
// do some custom exception handling here
return new Error("Go away, I am dying!");
}
triggerTheWarnAndDie(); // Go away, I am dying!
dontTriggerTheWarnAndDie(); // I should run!
Here is a JsFiddle Example
use the
return;
keyword to exit
*This is just a quick workaround. You may want to look into error checking and exceptions...
I'd suggest using promises but its not supported natively in all browsers. We can use callbacks where the code inside the callback only gets executed when warnAndDie allows it to execute.
function warnAndDie(shouldDie, fn) {
if(shouldDie) {
console.log("go away, i'm dying!");
// TODO: some code to cause the calling function to exit early
return;
}
fn();
}
function triggerTheWarnAndDie() {
shouldWarnAndDie(true, function () {
console.log("I should never run!");
} );
}
function dontTriggerTheWarnAndDie() {
shouldWarnAndDie(false, function () {
console.log("I should run!");
} );
}
I have the following example:
function foo1 (callback) {
if (!foo2(callback)) {
return;
}
console.log("Doing something");
/* do something */
}
function foo2 (callback) {
return callback ();
}
foo1 (function () {
console.log ("Hello World!");
});
I want to remove the if from foo1. Can I stop foo1 execution calling foo2? I am looking for something like this:
function foo1 (callback) {
foo2(callback); // calling foo2 this way I want to prevent
// the console.log below to be executed
console.log("Doing something");
/* do something */
}
Is there any way to do this?
Note that I don't want to throw an error. I just want to call the callback function and to stop the function execution.
Use case
Instead of this:
function a (options, callback) {
callback = callback || function () {};
if (typeof callback !== "function") {
callback = function (err) { console.log (err); }
}
if (!options.someField || options.someField.constructor !== Object) {
return callback ("someField should be an object");
}
/* do something */
}
I want to have:
function a (options, callback) {
validateFunction (callback, callback);
validateObject (options, callback);
validateObject (options.somField, callback);
/* do something */
}
If one of the validate* functions fails it should send the error via callback and stop a function execution.
If you can use promises:
function a (options) {
return validateObject(options).then(function(){
return validateObjecT(options.somField);
}).then(function(){
return validateObjecT2(options.somField);
}).then(function(){
return validateObjecT3(options.somField);
}).then(function(){
return validateObjecT4(options.somField);
}).then(function(){
/*do something*/
});
}
var validateObject = Promise.method(function(object) {
// Because this is inside Promise.method, thrown error
// will be equal to return Promise.reject(new Error("invalid"));
if (typeof object !== "object") throw new Error("invalid");
});
Alternatively function a can be also done like this:
function a (options) {
// If any validation fails, the do something is skipped
// and the code resumes at the next .catch() with the validation
// error passed as parameter
return Promise.all([
validateObject(options),
validateObject2(options),
validateObject3(options),
validateObject4(options),
validateObject(options)
]).then(function(){
/*do something*/
})
}
a({}).then(function() {
// Validation succeeded and everything was done
}).catch(function(e) {
// Validation or something else failed, e is the rejection error
});
Btw don't use strings as errors, a string is not an error.
That is, never do:
throw "foo";
callback("foo");
reject("foo") // When using promises
Instead do:
throw new Error("foo");
callback(new Error("foo"));
reject(new Error("foo")) // When using promises
There is a way, use throw
function foo2(callback) {
// do what you want to do
throw true;
}
And then catching it
try {
foo1();
}
catch (e) {
// if false, real error,
}
But it appears at a strange design. I hope that you have a valid reason and that it's clear to others whom is reviewing your code in the future.
I would use if statements:
function a (options, callback) {
if (!validateFunction (callback)) return;
if (!validateObject (options, callback)) return;
if (!validateObject (options.somField, callback)) return;
/* do something */
}
where the validateFunction function does not necessarily need 2 parameters if you call it always from such a scenario and the validate... functions always return a boolean with the result of the validation AND calling the callback in case of error.
function validateObject (options, errorCallback) {
if (!options.someField || options.someField.constructor !== Object) {
errorCallback("someField should be an object");
return false;
}
return true;
}
As many purists say, building an execution flow using try catch is not the right thing to do. There is also the performance issue. Using try catch is less performant then the control statements (e.g. if)
And there is though a try catch version that is faster and produces less code but I still don't prefer it because it is less clear in the code:
function a (options, callback) {
try {
validateFunction (callback);
validateObject (options);
validateObject (options.someField);
catch (err) {
callback(err);
return;
}
/* do something */
}
function validateObject (options, errorCallback) {
if (!options.someField || options.someField.constructor !== Object) {
throw "someField should be an object";
}
}
take a boolean for your function
function foo1(callback, exe) {
if (exe) {
foo2(callback);
} else {
console.log("Doing something");
/* do something */
}
}
Given this code:
var something = function(callback) {
if(condition) {
Mongoose.findOne(id, function(err, doc) {
if(doc) {
callback(doc);
} else {
callback();
}
});
} else {
callback();
}
}
How would I rewrite it in a cleaner way so that 'callback' is just called in one place. I assume I can wrap this entire thing somehow and do that - I've seen it but cannot get it quite right.
Since you said there are complex steps to call the callback, try the below
var something = function(callback) {
var callCallback = function(doc){
//do all other things you want to do to call the callback
callback(doc);
};
if(condition) {
Mongoose.findOne(id, function(err, doc) {
if(doc) {
callCallback(doc);
} else {
callCallback();
}
});
} else {
callCallback();
}
}
var something = function (callback) {
var f = function (e, d) { callback(d) };
if (condition) {
Mongoose.findOne(id, f);
} else {
f();
}
}
my reasoning is that if d is false then we still can pass it on to callback and it will be the same almost as passing no arguments at all.
Given is the following code:
function two() {
return "success";
}
function one() {
two();
return "fail";
}
If you test the code by calling function one(), you will always get "fail".
The question is, how can I return "success" in function one() by only calling function two()?
Is that even possible?
Regards
You can't make a function return from the function that called it in Javascript (or many other languages, afaik).
You need logic in one() to do it. E.g.:
function one() {
return two() || "fail";
}
function one() {
return two();
}
You could do it, using a try-catch Block, if your function one anticipates a probable non-local-return as well as function two like this using exceptions:
function two() {
throw {isReturn : true, returnValue : "success"}
}
function one () {
try {
two()
} catch(e) {
if(e.isReturn) return e.returnValue;
}
return "fail";
}
, I believe.
function one() {
return two();
}