33

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
  • 30,334
  • 10
  • 78
  • 137
Domysee
  • 12,718
  • 10
  • 53
  • 84
  • 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

12

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,572
  • 3
  • 42
  • 74
Andreas Møller
  • 839
  • 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
  • @Bergi can you explain how that is relevant here (ideally give a better solution from Jquery deferred object to ES6 promise object ? – kofifus Jun 04 '23 at 06:11
  • @kofifus See [here](https://stackoverflow.com/a/31327725/1048572) and also in the OP – Bergi Jun 04 '23 at 14:03
  • @Bergi I'm sorry I don't understand how this applies here – kofifus Jun 05 '23 at 08:51
  • 1
    @kofifus I'm saying that the OP should use the code that he is currently using, as presented in the question, and *not* use the code suggested in this answer. This `toPromise` function makes no sense, it already exists as part of the native API: it's called `Promise.resolve`! – Bergi Jun 05 '23 at 13:01
  • Ah I see! thanks – kofifus Jun 06 '23 at 03:36
12

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
  • 6,033
  • 11
  • 48
  • 62
nox
  • 331
  • 1
  • 4
  • 13
  • 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
  • 5,521
  • 4
  • 30
  • 35