views:

53

answers:

1

How does one return from a closure, without returning from the containing function?

In the following function, the return statement actually returns from GM_xmlhttpRequest: not the closure. Naturally I can see that I could arrange my code so that that execution drops off the end of the closure, but I'm curious as to how to early return in the example.

function GM_xmlhttpRequest(details, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState != 4)
      return; // <-- zomg returns from parent function wtf
    if (xhr.status != 200)
      callback(null);
    callback(xhr);
  }
  xhr.open('GET', details.url, true);
  xhr.send();
};
+1  A: 

return will only ever exit the callee (current function) and return control to the caller (calling "parent" function), it will never the return from the caller. In the situation you describe, the callee is the anonymous function set to onreadystatechange and there is no caller (per se).

GM_xmlhttpRequest returns undefined after the xhr.send() line before the onreadystatechange function runs because there is no return statement and the XHR is asynchronous. The "zomg wtf" line will just exit that anonymous function since there is no caller to pass control back to.

From ECMA-262, 3rd and 5th editions (section 12.9 The return statement):

A return statement causes a function to cease execution and return a value to the caller. If Expression is omitted, the return value is undefined. Otherwise, the return value is the value of Expression.

Andy E
Adjusting the closure so it doesn't use return, results in the closure being called several times with different `readyState` values. The explicit return terminates the function prematurely, and no more calls are made.
Matt Joiner