Travis Tidwell Travis Tidwell - 4 months ago 10
Javascript Question

How do I convert Q.defer() to Promise for instance variables?

I am currently looking to convert a library that uses Q.defer() for promise handling to use ES6 Promises. I understand the basics on how to convert Q.defer() to Promise, but every example I have ran into does not talk about the structure that I am running into where I need to convert class instance variables away from Q.defer() to Promises that do NOT resolve immediately. For example, take the following code.

import 'Q' from 'q';
class Service {
constructor() {
this.items = Q.defer();

// This would then make a call to some backend service... setTimeout to simulate.
setTimeout(() => {
this.items.resolve(['one', 'two', 'three']);
}, 1000);
}
getItems() {
return this.items.promise;
}
}


I would like to use this class like the following.

let service = new Service();
service.getItems().then((items) => {
console.log(items);
});


Currently, I am reading that you should use Promise.resolve() to create a similar structure, however, if I replace Q.defer() with Promise.resolve(), the promise resolves immediately with no items, which is not what I am wanting. Here is what I was thinking could be the replacement.

class Service {
constructor() {
this.items = Promise.resolve();

// This would then make a call to some backend service... setTimeout to simulate.
setTimeout(() => {
this.items.then(() => {
return ['one', 'two', 'three'];
});
}, 1000);
}
getItems() {
return this.items;
}
}


This doesn't work since the promise resolves immediately...

How do I convert the code above to use Promises?

Answer

The problem is that deferred is not part of the Promise specification and a bit of an anti-pattern so native Promises don't have the same concept. This would work in native, but I'm not sure if you can wrap your methods like this.

class Service {
  constructor() {
    this.items = new Promise(deferred)
    function deferred(resolve, reject) {
      setTimeout(() => {
      resolve(['one', 'two', 'three']);
      }, 1000);
    }
  }
  getItems() {
    return this.items;
  }
}