0

I want to pass to the then method the data, but when I do this by giving it this.passedResolve it gets undefined

    function Promises(callback){
      if(callback){
        callback(Promises.prototype.resolve, Promises.prototype.reject);
      }
    }

    Promises.prototype.resolve = function(data){
      this.passedResolve = data;
    }

    Promises.prototype.reject = function(err){
      console.log(new Error(err));
    }

    Promises.prototype.thens = function(cb){
      cb(this.passedResolve);
    }

    function loadImg(url){
      return new Promises(function(resolve, reject){
        var el = new Image()
        el.onload = function(){
          resolve(el)
        }
        el.onerror = function(){
          reject('Error')
        };
        el.src = url;
      })
    }

    loadImg('https://s-media-cache-ak0.pinimg.com/736x/12/64/da/1264da4a3f18207dc22592102abae40d.jpg').thens(function(e){
      console.log(e)
    })

    var x = new Promises()
    console.log(x)
  • Note that your promise implementation is far from being compliant with the Promise/A+ specification. For instance, you now could call `resolve` twice with a different value, making the promised value change. That is not allowed. Also, the `then` callback should only be called when the promised value is available, not before, and it should always run asynchronously. Have a look at [the second half of my answer](http://stackoverflow.com/a/42057900/5459839) to a previous similar question. – trincot Apr 20 '17 at 12:34

1 Answers1

1

This is because the local this variable escapes the scope. You need to bind it to the current instance.

function Promises(callback){
  if(callback){
    callback(Promises.prototype.resolve.bind(this), Promises.prototype.reject.bind(this));
  }
}

Otherwise, the passedResolve function will be assigned into another object. So when Promises wants it, it gets undefined. I hope that makes sense.

JavaScript objects have a few quirks here and there, as you can see.

Tobe Osakwe
  • 729
  • 7
  • 18
  • Ok, Do you mean put it in the constructor function? btw the ```passedValue``` is a property not method/function – Mahmoud Mohamed Zakaria Apr 20 '17 at 12:34
  • Yes, put it in the constructor. And also, properties are technically functions (getters, sometimes setters). – Tobe Osakwe Apr 20 '17 at 12:35
  • I tried all of those "getters, setters or even put one in the constructor" when I log the```passedValue``` in the```resolve``` method it works fine but when I pass it to the```cb``` of the```thens``` it returns```undefined``` – Mahmoud Mohamed Zakaria Apr 20 '17 at 12:38
  • Well, there is a logic error inside your implementation. The way you have it, your `thens` function calls `passedResolve` before it is ever assigned to. Which is why it returns `undefined`. You need to store the `then` callback as a property, as well. `resolve` should invoke the callback, not assign one. I'll post a Gist link in a minute – Tobe Osakwe Apr 20 '17 at 12:41
  • No ```resolve``` method runs first because I return ```new Promises``` first and inside it I envoke the ```resolve```, ```thens``` make the change for the ```passedResolve``` after that, Ok take your time. – Mahmoud Mohamed Zakaria Apr 20 '17 at 12:46
  • Yes, but your `resolve` isn't calling the callback, which is my point. This is how you do it correctly; https://gist.github.com/thosakwe/153ee43dd9d004abb2e5f1be8c3f5769 – Tobe Osakwe Apr 20 '17 at 12:47
  • Yeah, it works now, but what the hack is going on? I don't get it – Mahmoud Mohamed Zakaria Apr 20 '17 at 12:57
  • You had your logic the wrong way around. Whichever callback you give to `then` should be cached until it is needed. `resolve` should never set the callback; it should only call the callback if it is present, or save the value for when the callback is added. – Tobe Osakwe Apr 20 '17 at 12:59
  • Ooh, Correct me if I'm wrong, we have an event loop in our ```onload``` event so the ```then``` function is like a listener/subscriber and ```resolve``` is an ```emitter``` keeps searching for finished loading image and when it is done it calls the callback!! – Mahmoud Mohamed Zakaria Apr 20 '17 at 13:04
  • There's no event loop, it's just reactive. `then` is a listener, and `Promises` is the dispatcher/emitter. `resolve` just says "hey, we have value, time to run the callback". Promises basically just say "hey, run this function whenever there is a value." – Tobe Osakwe Apr 20 '17 at 13:06
  • Cool! but why we bind the ```Promises```'s callback args to ```this``` ```callback(Promises.prototype.resolve.bind(this), Promises.prototype.reject.bind(this));``` – Mahmoud Mohamed Zakaria Apr 20 '17 at 13:08
  • Because in JavaScript, `this` can change, and refers to the current scope, rather than the current object. `this` can even be the window, console, Node.js, an object, anything. So we have to explicitly set this – Tobe Osakwe Apr 20 '17 at 13:09
  • Yeah I see, Thank you Amigo – Mahmoud Mohamed Zakaria Apr 20 '17 at 13:12
  • No problem! Best of luck. – Tobe Osakwe Apr 20 '17 at 13:14