i have group of bind's, which gets trigger inside a function from before and after the code. like following:
function global() {
before(); // call all before binds here
//... mainFunction code...
after(); // call all after binds here
}
if one of functions inside before(); callback wants to exit or stop the global() from running further, how can i stop it, without checking the return values?
The only way to achieve this without checking the value returned, is to raise an exception by throwing an error.
function before() {
throw new Error('Ending execution');
}
function after() {
console.log('Have you met Ted?');
}
function global() {
before();
// never reaches here
after();
}
global(); // Error: Ending execution
console.log('foo'); // not executed
If you have global invoked somewhere and want any code following it's invocation to continue being executed, you'll need to wrap it with a try..catch, for example
function global() {
try {
before();
// never reaches here
after();
} catch (e) {
console.log(e); // log error. Leave this block empty for no action
}
}
global(); // Error logged
console.log('bar'); // still executed
Related
I'm having a synchronization and loading issues with some JS modules when the program starts. This error only shows up once at the beginning and then everything works, so it is an obvious sync problem.
The code:
//pyramid of doom
function initGame(){
initWorld(function(){
initPlayer(function(){
initBots(function(){
console.log("Game Loaded!");
update();
})
})
});
}
function initWorld(callback){
world.init(worldParams);
callback&&callback();
}
function initPlayer(callback){
player.init(scene,playerParams,world.getPhysicModel());
callback&&callback();
}
function initBots(callback){
bots.init(scene,botsParams,world.getPhysicModel());
callback&&callback();
}
function update() {
world.update(1/60);
player.update();
bots.update();
}
initGame();
The following is the error I'm getting.
Bots.js:112 Uncaught TypeError: Cannot read property 'mixer' of undefined
at Bots.update (Bots.js:112)
at update (Final.html:160)
What am I doing wrong? How can I synchronize the execution of the init functions?
(What I think that is going on is that the execution of initBots doesn't reach it end before the udpdate function starts to run.)
You can find the Bots.js module in my repository at ( 1 )
In bots.init you execute new THREE.ColladaLoader().load which looks to be asynchronous.
In its callback, you fill your _bots array (self._bots[modelLoaded] = bot;).
However, you execute bots.init() and do not wait for these asynchronous calls to complete before executing the initBots function callback. In the case of initGame execution, this callback executes update(), which in turn executes bots.update(), which tries to access this._bots[i].mixer with i index up to this._botsParams.length, i.e. a pre-defined value that does not account for how many items have been actually filled in _bots array.
Hence your error message: the array has no items yet at some indices, and trying to read a property on undefined throws an error.
Conclusion: common asynchronous issue.
You need to be passing the callbacks into the init functions. Guessing from a brief look at your bots code, they are not expecting to receive callbacks so you might be in for a rebuild.
You can't tell from the outside of an async function if it is done yet!
Equivalent to what you are doing:
let result = undefined
function takeTime () {
setTimeout(function() {
result = 'hello!'
}, 100)
}
function callback () {
console.log(result)
}
function run (callback) {
takeTime()
callback && callback()
}
run(callback) // undefined! takeTime has not finished yet
What you need to be doing:
let result = undefined
function takeTime (callback) {
setTimeout(function() {
result = 'hello!'
callback()
}, 100)
}
function callback () {
console.log(result)
}
function run (callback) {
callback && takeTime(callback)
}
run(callback) // 'hello!', the callback was only called once the takeTime function completed
I need to terminate the javascript from a function so that it doesn't execute the next block of codes and other functions called by the script, which follows the current function.
I found this existing question in SO : How to terminate the script in Javascript , where the solution is given as to trigger an error / exception which will terminate the script immediately.
But my case is different because, My purpose of terminating the script is to prevent an error which will come from the next functions, if the current function doesn't stop execution of the script. So, triggering another error to prevent an error is no way solving my purpose!
So, is there any other way of terminating the javascript instead of throwing an error / exception?
Please read my question properly before marking as duplicate, I have already explained why it doesn't solve my problem with the question I referred!.
Since you're inside a function, just return.
Reading into your question a little more that it doesn't execute "other functions called by the script", you should return a boolean. For example, return false if you don't want the rest called, then wrap the remaining statements in an if:
function Foo() {
if (weAreInLotsOfTrouble) {
return false;
}
return true;
}
DoSomething();
DoSomethingElse();
if (Foo()) {
DoSomethingDangerous();
}
Try using jQuery.Callbacks() with parameter "stopOnFalse" ; jQuery.when() , jQuery .then()
var callbacks = $.Callbacks("stopOnFalse");
function a(msg) {
var msg = msg || "a";
console.log(msg);
return msg
}
// stop callbacks here
function b() {
var msg = false;
console.log(msg)
return msg
}
// `c` should not be called
function c() {
var msg = new Error("def");
console.log(msg)
return msg
}
callbacks.add(a,b,c);
$.when(callbacks.fire())
.then(function(cb) {
// `c` : `Error`
if (cb.has(c)) {
console.log("callbacks has `c`"
, cb.has(c));
// remove `c`
cb.remove(c);
console.log(cb.has(c));
// empty `callbacks`
cb.empty();
// do other stuff
cb.add(a);
cb.fire("complete")
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
Why does 'good' and 'Error is called' write the console in the below example?
My understanding is that you give then() something to run on success and something to run on fail?
var deferred = Q.defer();
function two() {
deferred.resolve();
return deferred.promise;
}
two().then(console.log('good'),console.log('Error is called'));
Q.then function can actually accept three parameters and all of them should be functions.
The success handler
The failure handler
The progress handler
When you do,
two().then(console.log('good'), console.log('Error is called'));
you are actually passing the result of executing both the console.logs to the then function. The console.log function returns undefined. So, effectively, you are doing this
var first = console.log('good'); // good
var second = console.log('Error is called'); // Error is called
console.log(first, second); // undefined, undefined
two().then(first, second); // Passing undefineds
So, you must be passing two functions to the then function. Like this
two().then(function() {
// Success handler
console.log('good');
}, function() {
// Failure handler
console.log('Error is called')
});
But, Q actually provides a convenient way to handle all the errors occur in the promises at a single point. This lets the developer not to worry much about error handling in the business logic part. That can be done with Q.fail function, like this
two()
.then(function() {
// Success handler
console.log('good');
})
.fail(function() {
// Failure handler
console.log('Error is called')
});
You have to pass functions to .then. What you did is you called console.log('good') and passed the result of calling it (which is undefined) to .then. Use it like that:
two().then(
function() { console.log('good'); },
function() { console.log('Error is called'); }
);
I have this self made function called succeeder which is supposed to try to run a function called func and if it fails to try and run it again after an interval.
This works great the first time and when func is called for the second time after setTimeout it fails and this seems out of context.
Can you think of anything that is not right in this snippet?
succeeder({
func : function () {
!this.dbOpen && this.init();
return true;
},
context : this,
interval : 2000,
success : function () { return true;}
});
function succeeder(opts) {
function run() {
try {
//_.delay(function(){opts.func();}.bind(opts.context), 2000);
setTimeout(function(){ return _.bind(opts.func, opts.context)(); }, 2000);
} catch (e) {
run(this.opts, this.interval);
}
}
run();
};
Your code doesn't do anything like the description. Also the description isn't clear: what does "if it [func] fails" mean? Does func throw an exception? Return false? Or what?
There is no code to check the return value from func, yet the example version of func returns true. What is the purpose of the true return value?
You have a try/catch block, which made me suspect you are talking about the func call throwing an exception. But this try/catch won't catch any exception that func throws!
That's because the try/catch is wrapping the setTimeout call. But func is not called from inside that try/catch block. It's called later, when the timeout fires, and the try/catch is no longer in effect at that time.
What is the opts.success function? It is never used.
Also, the code always takes a two-second delay before the first attempt to call func. Do you want that, or do you want the first call to be immediate and only take the delay if the call fails and you retry?
Here is a working example that does something like what you're talking about. I made the assumption that "fail" means "throw an exception", and that you don't want any delay on the initial func call.
To test the code I used a func function that runs a countdown and throws an exception each time and finally succeeds when the countdown reaches 0.
Run this with the debug console open so you can see the console.log() messages:
function Test() {
this.countdown = 5;
succeeder({
func: function () {
console.log(
this.constructor.name,
'countdown:',
this.countdown
);
if( this.countdown-- ) {
console.log( 'func throwing error' );
throw new Error( 'fail' );
}
console.log( 'func success!' );
},
context: this,
interval: 1000,
success: function () { return true; }
});
};
new Test;
function succeeder(opts) {
var func = _.bind( opts.func, opts.context );
function run() {
try {
func();
} catch (e) {
setTimeout( run, opts.interval );
}
}
run();
};
I am trying to write a function that returns an object representing the position of the device: I have tried:
function getDevicePosition () {
var positionObject;
if (isDeviceReady) {
navigator.geolocation.getCurrentPosition(function (position) {
positionObject = position;
console.log('location updated');
console.log(positionObject.coords.longitude);//1. works
}, function (err) {
console.log('Failed to get device position' + err);
return null;
});
} else {
warnUser();
return null;
}
console.log(positionObject.coords.longitude);//2. doesnt work as positionObject is null.
return positionObject;
}
Notice that I have added comments marking statement 1 and statement 2. If I initialized position object in statement 1. Why is it undefined in statement 2?
Because getCurrentPosition is an asynchronous method. The line marked as 2 will run before the callback function gets a chance to execute, so positionObject will still be undefined.
You need to move all code that depends on positionObject inside the callback to getCurrentPosition.
The call to navigator.geolocation.getCurrentPosition() is asynchronous, so the execution of the rest of the function does not wait until it is finished.
So your function is at execution basically reduced to this:
function getDevicePosition () {
var positionObject;
if (isDeviceReady) {
// trigger some asynch function ...
} else {
warnUser();
return null;
}
console.log(positionObject.coords.longitude);
return positionObject;
}
From this code it should be pretty obvious, that at the point, your code reaches the console.log() your positionObject is not set, thus resulting in the error.
EDIT
With respect to your comment. The general design principle for such tasks is as follows:
// original function (triggered by a button or whatever)
function trigger() {
// do some calculations before
// trigger the position-retrival
navigator.geolocation.getCurrentPosition(function (position) {
// get the position
// ...
// call the handling function
doStuff( position );
});
}
// the function to do stuff based on the position
function doStuff( position ) {
// ...
}