1

I'm currently reading 'You Don't Know Javascript' and ran across a problem with in an example of how to address a callback never running.

In the example listed below, I'm not sure how it works.

So the bottom code works first to check if there is an error or if the data is valid then the ajax request gets called with timeoutify(foo, 500).

When timeoutify is running it uses foo and 500 as parameters, it runs the first setTimeout function and in 500 milliseconds a timeout error will occur if the setTimeout isn't cleared.

However, the part I'm having trouble with the 2nd half starting with the if(intv) part. Doesn't timeoutify always get if(intv) set to true because the setTimeout is running first so the statement always return the 2nd half? When will the error timeout happen?

function timeoutify(fn,delay) {
  var intv = setTimeout( function(){
               intv = null;
               fn( new Error( "Timeout!" ) );
             }, delay );
  return function() {
    // timeout hasn't happened yet?
    if (intv) {
        clearTimeout( intv );
        fn.apply( this, arguments );
    }
  };
}

Here is the preceding code:

    // using "error-first style" callback design 

    function foo(err,data) {
      if (err) { 
        console.error( err );
      } else {
        console.log( data ); }
      }
      ajax( "http://some.url.1", timeoutify( foo, 500 ) );

2 Answers 2

2

The first thing that I would like to specify is that timeOutify is not being passed on as a callback function, if it was a callback than the "(foo,500)" should be omitted. So we are actually executing the timeOutify(foo, 500) with the callback function foo and 500 will be the wait time value and when timeOutify is executing it performs the following steps: 1. If starts the timeout function 2. It returns a function with an if block in it.

So if the ajax call succeeds before the timeout, it will execute the returned function i.e.

    // timeout hasn't happened yet?
    if (intv) {
        clearTimeout( intv );
        fn.apply( this, arguments );
    }
  };

intv is true by now as timeout function haven't executed till now, so it will stop the timeout to happen by clearTimeout and call the foo function with the context of the data returned from the ajax call.

fn.apply( this, arguments ); //is being used for explicit binding.

The other case when the ajax doesn't succeed in the given time of 500ms than intv is set to null so that the if check in the latter part of code fails and foo function will be executed with the error object as an argument.

This is the basic flow of this code.

Sign up to request clarification or add additional context in comments.

Comments

1

Doesn't timeoutify always get if(intv) set to true because the setTimeout is running first

No. intv is set to true by the function passed to setTimeout and that function doesn't get called until the the time specified by the delay has passed.

2 Comments

I'm still a little confused. The function inside of the setTimeout, once it runs. It will turn set intv into true? I thought that it will set the intv = null after 500 seconds. When does the return half get a chance to activate during this queue? I guess the main thing I'm not too sure is the order in which these events are happening. Could someone clarify it a bit more?
It's 500ms not 500s. That's 500ms for the returned function to be called in.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.