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(); };
Advertisement
Answer
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(); };