0

I'm not well versed in JavaScript. I have an object below (Foo.bar) that I want to both feed and print items from a queue every 100 ms.

var Foo = Foo || {};
Foo.bar = {
    initialize: function () {
        this.feedQueue();
        this.consumeQueue();
    },
    queue: [],
    consumeQueue: function () {
        if (this.queue > 0) {
            var item = this.queue.shift();
            console.log(item);
        }
        setTimeout(function () {
            this.consumeQueue();
        }, 100);
    },
    feedQueue: function () {
        this.queue.push(Math.random());
        setTimeout(function () {
            this.feedQueue();
        }, 100);
    }
};
Foo.bar.initialize();

Within the consumeQueue function "this.queue" never updates. It always is empty.

Can anyone help me out here with what I am doing wrong?

1
  • 3
    Classic timeout has different context (this) issue Commented Sep 11, 2014 at 22:05

4 Answers 4

4

You need to bind the scope to your timeout functions, otherwise this has a different context.

setTimeout((function () {
    this.consumeQueue();
}).bind(this), 100);

Fiddle

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

1 Comment

setTimeout(this.consumeQueue.bind(this), 100)
4

why bind, why argument?

setTimeout((function () {
    Foo.bar.consumeQueue();
}), 100);

4 Comments

Why downvote? Yes, it should be Foo.bar instead of just Foo. But it is an working alternative (+1)
Aaaaa.. yes! i not attentive. But what profit for using call or arguments?
@Deep By using bind or arguments you don't create a closure, that's the only point I can see but your answer deserves an upvote to me.
2

In your callback function this is equal to window because this is omitted when calling the callback.

As RienNeVaPlus said in his answer you can use bind like this

setTimeout((function () {
    this.consumeQueue();
}).bind(this), 100);

OR you can pass this as a parameter to your callack function

setTimeout(function (context) {
    context.consumeQueue();
}, 100, this);

In both case if you use IE as a browser, you will need IE9 at least.

1 Comment

Maybe. And I'm thinking so TS have only one instance of queue. And more im think so call and arguments create recursive pointers. And this maybe make memleak on IE. in this I am not sure it is necessary to know
1

As a final alternative to binding or passing it to the callback function, this should work pre IE9:

...

consumeQueue: function () {

    if (this.queue > 0) {
        var item = this.queue.shift();
        console.log(item);
    }
    var that = this;
    setTimeout(function () {
        that.consumeQueue();
    }, 100);
},

...

Comments

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.