2

Most probably I made some obvious context or scope mistake, but I cannot figure out what I am doing wrong. Here is a small example to illustrate the issue I am having.

When having the following main.js javascript:

$(function() {

    /**
     * Returns a promise that resolvses the provided parameter `something`
     * after 4 seconds.
     */
    function async(something) {

        var deferred = $.Deferred();

        setTimeout(function() {
            deferred.resolve(something);
        }, 4000);

        return deferred;
    }

    /**
     * Some object with a name and response property.
     */
    var SomeObj = function(name) {

        this.name = name;
        this.response = null;

        this.init();
    }

    SomeObj.prototype.init = function() {

        self = this;

        async(this.name).then(function(response) {

            self.setResponse(response);
        });
    };

    SomeObj.prototype.setResponse = function(response) {

        this.response = response;

        console.log(this);
        console.log(response);
    };

    objA = new SomeObj('a');
    objB = new SomeObj('b');
});

That is executed within the empty HTML page:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
    <script src="bower_components/jquery/dist/jquery.js"></script>
    <script src="main.js"></script>
  </head>
  <body>
  </body>
</html>

And with jquery installed in the same directory using:

bower install jquery

A the bottom of the javascript file, two objects are initialized with a name property. During initialization, these objects set their response property to the same value, that is returned as promise by the async function. This function simply resolves the input parameter after four seconds.

With this script I would have expected that (after waiting four seconds) the response property of ObjA is set to a and the response property of objB is set to b. However, the console shows me the following result:

> SomeObj {name: "b", response: "a"}
> a
> SomeObj {name: "b", response: "b"}
> b

Apparently the setResponse function of objB is called in both cases. But why?

Bastiaan van den Berg
  • 1,585
  • 1
  • 14
  • 20

1 Answers1

2

Here's your problem:

SomeObj.prototype.init = function() {
    self = this;

self is a global variable, overwritten by the second instance, and referred to by both callbacks. Make it

    var self = this;

and you code will work. (That said, it's not the best idea to create a promise in your constructor and asynchronously create that .response property)

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks! And sorry for posting this beginners mistake that keeps popping up the javascript-day after a python-night. – Bastiaan van den Berg Jun 18 '15 at 13:17
  • And thanks for the advice. However, in the real case I asynchronously request a 'title' from the server which is upon resolving inserted into the HTML page (it's for a jquery plugin). I do not store the returned value, so I think that is less of an issue. – Bastiaan van den Berg Jun 18 '15 at 13:28