Search code examples
javascriptjquerypromiseecmascript-5geo

Rewrite ES6 Promises using jQuery.Deferred()


I'm currently writing code for the browser and restricted to using ES5. I do have access to jQuery, and I need to rewrite several large functions that are currently using ES6 promises. For example:

  function getLocationFromIp() {
    return new Promise(function (resolve, reject) {
      $.ajax({
        url: someUrl,
        data: {},
        xhrFields: {
        withCredentials: true
        },
        success: function (data) {
          resolve(data);
        },
        error: function (err) {
          reject(err);
        }
      });
    }).then(transformIpGeoDataToLocation);
  }

I understand that I have access to .resolve() and .reject(), but I'm struggling with the implementation. Would it look something like this?

 function getLocationFromIp() {
   return $.Deferred(function (dfr) {
     $.ajax({
       url: someUrl,
       data: {},
       xhrFields: {
         withCredentials: true
       },
       success: function (data) {
        dfr.resolve(data);
       },
       error: function (err) {
         dfr.reject(err);
       }
     });
   }).promise().then(transformIpGeoDataToLocation);
 }

I'm also looking into bluebird as a fallback, but I'd like to give this approach a shot, thanks! Unfortunately, Babel and other transpilers are not an option.


Solution

  • So, if you don't want to use ES6 promises and do want to use jQuery promises, the function call $.ajax() already returns a jQuery promise so there is no need to wrap it in another promise. You can just directly return the promise that $.ajax() already returns:

      function getLocationFromIp() {
          return $.ajax({
            url: someUrl,
            data: {},
            xhrFields: {
            withCredentials: true
          }).then(transformIpGeoDataToLocation);
      }
    

    Note: jQuery promises (particularly from Ajax calls) in version of jQuery prior to 3.x don't resolve with exactly the same type of data that ES6 promises do. In particular a jQuery Ajax promise resolves with three arguments (not the ES6 standard of one). The first argument is the result one would typically use. You can work with that just fine, but will need to make sure your .then() handlers such as transformIpGeoDataToLocation are aware of that.