0

I use LocalForage for persistent storage in the browser. I also (unfortunately) use jQuery's deferreds and promises everywhere else in the project. I'm trying to use $.when to collect the responses from many LocalForage requests:

var results = _.map(keys, localForage.getItem);
$.when.apply($, results).then(function() {
  // iterate over the arguments object
});

This... doesn't work. I've verified that the results array correctly contains many ES6 promise objects (or shim promises from LocalForage's built in shim, in some browsers). These objects don't have a .promise function on them, so $.when doesn't recognize them as promises, and calls the anonymous then function immediately with all of the promises as arguments. As a test, I tried changing the above code to

var results = _.map(keys, _.constant($.Deferred().resolve(false)));
$.when.apply($, results).then(function() {
  // iterate over the arguments object
});

and it works correctly.

What is the best solution to this? Is there a way to convert the ES6/shim promises into jQuery promises, other than var deferred = $.Deferred(); es6Promise.then(deferred.resolve, deferred.reject)?

zrneely
  • 1,802
  • 3
  • 17
  • 26
  • Not really, but there's no reason to do that. Rather convert them the other way round! See http://stackoverflow.com/a/31327725/1048572 – Bergi Aug 20 '15 at 18:23
  • I don't think that the shim is applied globally by LocalForage due to my requirejs configuration, and the project needs to support browsers that don't support ES6 promises natively. I'd like to avoid adding another library to the project as well. – zrneely Aug 20 '15 at 18:28
  • To me, [the docs](https://github.com/mozilla/localForage#promises) read like it does rely on a global available ES6 promise implementation, and includes a polyfill for that. Just try it out whether it's available - and fix your requirejs config othewise – Bergi Aug 20 '15 at 18:58
  • Well, that sort of makes this a non-issue for me - thanks, you were absolutely right. – zrneely Aug 20 '15 at 19:29
  • I'll make it an answer :-) – Bergi Aug 20 '15 at 19:33

1 Answers1

2

What is the best solution to this?

Don't do it. Don't use $.when.apply. Don't convert ES6 promises to jQuery deferreds.

ES6 promises are in so many ways better than jQuery deferreds - most importantly, they follow Promises/A+ and are interoperable, making assimilation a non-issue. You can easily use them with jQuery. In your case, it should be

var results = _.map(keys, localForage.getItem);
Promise.all(results).then(function(arr) {
  // iterate over arr - no more arguments object!
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375