Can someone please explain this code snippet on asynchronous programming from YDKJS book 5

Hey campers,

I’ve been trying to understand this for hours but its just going over my head, help would be much appreciated.

" What about the trust issue of never being called? If this is a concern (and it probably should be!), you likely will need to set up a timeout that cancels the event. You could make a utility (proof-of-concept only shown) to help you with that:

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, [ null ].concat( [].slice.call( arguments ) ) );
		}
	};
}

Here’s how you use it:

// 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 ) );

"

thank you,
see https://github.com/getify/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch2.md#trying-to-save-callbacks

Where are you getting stuck? Is it the intv check? The thing to note there is that the returned function isn’t ran immediately (like an IIFE), it’s only constructed there. So it is ran when ajax does its asynchronous bit, at which point intv either still holds the timer ID or it is null from the function called on its expiry.

1 Like

doesnt the timeoutify function itself need to be invoked (after receiving a response) in order to set the timer and return the anonymous function? and if so doesn’t that defeat the purpose of what timeoutify is intending to do.

i guess i don’t understand how or when the timeoutify function is immediately invoked without being called.

thank you for your time

timeoutify is called before making any ajax request.

When timeoutify was called in the last line, it first set up a 500 ms timer, then returned a function. If 500 ms elapsed before the ajax request completes, the callback in the timer fires foo, but passes it an error. Otherwise the ajax utility calls the returned function (which clears the timer and calls foo).

2 Likes

thank you very very very much,

what I misunderstood was when exactly timeoutify was called.

I was mistaking this:
ajax("http://some.url.1", timeoutify( foo, 500 ));
for this:
ajax("http://some.url.1", timeoutify);

i forgot that if a function is passed as a parameter with brackets it will immediately be invoked.

1 Like

How about this line then?
fn.apply( this, [ null ].concat( [].slice.call( arguments ) ) );
Why this? Why null?
What’s the point for [null].concat, wouldn’t that [].slice.call( arguments ) be enough already?

After some exploration, I think I finally understood this, and it turns out it’s actually wrong. It should be just fn.call(this, arguments)

But what the author intended it was to call fn with error set to null. That’s why it concats [null] with fn's arguments, which is the result of [].slice.call( arguments ). And that’s the problem. because fn's arguments are error and data, so we are passing error as a second argument to fn and data as a third argument, because the first one is always null. Since that’s not how fn expects to receive data, it’s wrong.