32

Is this the correct way to convert jQuery Deferred to a Promise?

var p = Promise.resolve($.getJSON('api/values', null));

Are there any other ways to do this?

What are the limitations? I've read somewhere that jQuery deferred does not support exceptions, so I assume that a promise created out of a deferred would neither. Is this correct?

Chris Martin
  • 29,484
  • 8
  • 71
  • 131
Domysee
  • 12,310
  • 10
  • 51
  • 80
  • If you wrap the deferred object with a ES6 promise, I would think that it would support exceptions. The code inside a promise could be both synchronous and asynchronous. – Johan Lindskogen Aug 25 '15 at 16:30

3 Answers3

10

I am not sure if that would work. I would recommend:

var p = new Promise(function (resolve, reject) {
  $.getJSON('api/values', null)
    .then(resolve, reject);
});

preferably you could create an adaptorfunction like:

var toPromise = function ($promise) {
  return new Promise(function (resolve, reject) {
    $promise.then(resolve, reject);
  });
});

var p = toPromise($.getJSON('api/values', null));
Mario
  • 6,363
  • 3
  • 39
  • 71
Andreas Møller
  • 819
  • 5
  • 9
  • Is there a way to do this and get rid of jQuery altogether. For a mobile app it'll be nice to avoid the overhead of adding jquery.min.js – A.Grandt May 13 '16 at 07:02
  • 2
    Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572) and just use `Promise.resolve`! – Bergi Oct 24 '16 at 21:13
10

Yes it should, the Promise.resolve() API supports thenable as argument. So passing a jquery defer object would work just fine.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve#Resolving_thenables_and_throwing_Errors

munchybunch
  • 5,863
  • 10
  • 46
  • 62
nox
  • 260
  • 4
  • 11
  • 6
    Bear in mind that this only works if you're only interested in the first jQuery ajax parameter, i.e. if you want `.then(function (data, textStatus, jqXhr) {})` then this won't work, as `Promises` support only a single argument. You'll need to manually convert the jQuery 'promise' into a `new Promise(...)` and marshal the arguments in there. – nicodemus13 Aug 09 '16 at 12:53
2

I would prefer composition:

const successCb1 = ()=>$.getJSON('api/values'),
successCb2 = (json)=>alert(json),
errorCb = (e)=>alert(e);
Promise
   .resolve()
   .then(successCb1)
   .then(successCb2)
   .catch(errorCb);
Shishir Arora
  • 4,983
  • 3
  • 27
  • 34