THEtheChad
THEtheChad

Reputation: 2432

Reassign variables stored in closure using a callback or global function

EDIT

Let me get more to the point. I'm trying to create a psuedo promise implementation. The idea here being that I have a callback that won't be executed until an asynchronous call is received. So I'm simply queueing up all the calls to this function until the time at which it's notified that it can be executed. The queue is emptied and any further call to the function is SUPPOSED to execute immediately, but for some reason, the function is still queueing. This is because, for whatever reason, my redefinition of the runner function is not working correctly. The code below was my sleep deprived, frustrated version of every thought that went through my head. Here's the actual code:

function Promise(callback){
  var queue    = []
    , callback = callback
    , runner   = function(){
        queue.push({
          context: this,
          args: Array.prototype.slice.call(arguments, 0)
        });
      }
  ;//var

  runner.exec = function(){
    for(var i = 0, ilen = queue.length; i < ilen; i++){
      var q = queue[i];

      callback.apply(q.context, q.args);
    }

    runner = callback;
  };

  return runner;
}

test = Promise(function(){
  $('<div/>').appendTo('#output').html(Array.prototype.slice.call(arguments,0).toString());
});

test(1,2);
test(3,4);
test.exec();
test(5,6);​

http://jsfiddle.net/a7gaR/


I'm banging my head against the wall with this one. I'm trying to reassign variables in a function from a call outside the function itself (ideally by passing a reassignment function as a callback). In the example I posted on jsfiddle, I made a global function that, in theory, has a reference to the variables contained within its parent function. Upon calling that external function, I expect it to reassign the values that the other function is using. It doesn't seem to work this way.

window.test = function temp() {
    var val = 7,
        func = function() {
            return val;
        };

    window.change = function() {
        window.test.val = 555555;
        $('<div>Changing ' + val + ' to ' + window.test.val + 
               '</div>').appendTo($output);
        val = window.test.val;
        temp.val = window.test.val;
        func = function() {
            return 'Why isn\'t this working?';
        }
    }

    return func();
}

var $output = $('#output');

$('<div/>').appendTo($output).html('::' + test() + '::');
window.change();
$('<div/>').appendTo($output).html('::' + test() + '::');

http://jsfiddle.net/YhyMK/

Upvotes: 1

Views: 242

Answers (3)

THEtheChad
THEtheChad

Reputation: 2432

I finally created a function that would perform this operation. The gist for it is here: https://gist.github.com/2586972.

It works like this...

You make a call to Defer passing the callback whose functionality you'd like to delay:

var deferredCB = Defer(function(){ console.log(this,arguments) };

deferredCB will now store all of the arguments you pass allowing them to be executed at some later date:

defferedCB(1);
defferedCB(2);

Now, when you're ready to perform the operation, you simply "execute" deferredCB:

defferedCB.exec();

Which results in:

// window, 1
// window, 2

All future calls to deferredCB will be executed immediately. And now that I'm thinking about it, I'll probably do a rewrite to allow you to reset deferredCB to it's pre-executed state (storing all the arguments again).

The key to making it work was having a wrapper function. Javascript simply won't let you reassign a function while it's being executed.

TADA!!!

Upvotes: 0

Wayne
Wayne

Reputation: 60414

The second time you call test you're creating a new local variable called func and defining a new window.change that closes over that new variable. The changes you made to the original func by calling the original window.change are not relevant in the second call.

Also note that the following line:

window.test.val = 555555;

...does not modify/refer to the val variable in the outer function. window.test.val refers to a property named val on the test object (which happens to be a function), not any local variable.

Upvotes: 1

Ned Batchelder
Ned Batchelder

Reputation: 375594

You are trying to refer to a local variable in a function with the syntax func.varname. That won't work, that's not the way local variables work.

Upvotes: 0

Related Questions