Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use native ES6 Promises + polyfill or a custom Promise library?

I want to switch my code to Promises/A+ API. My principal use will be to remove callbacks cascade

I need a solution:

  • The more sustainable as possible
  • With the smaller library size
  • The more native possible...

Solution 1: Native

I saw on caniuse http://caniuse.com/#feat=promises that the ES6 promise is pretty well implemented except for IE... A polyfill exists https://github.com/jakearchibald/es6-promise, so I can use it for IE.

Does anyone already used this solution, and is it viable?

Solution 2: External library

I can use alternative libraries like Bluebird, Q or when. Is there a very big advantage to use them?


UPDATE: @sdgluck Unlike my first idea, Bluebird appeared to bring Promises at a higher level! So I choose to use it.

like image 827
aprovent Avatar asked Oct 20 '15 07:10

aprovent


People also ask

What is promise polyfill?

Promise Usage. The promise is a constructor which accepts an executor function as a parameter. The executor function has a resolve callback, and a reject callback as its parameter. Once the Promise constructor is called, an async operation is initiated, say, an HTTP API call.

Are promises introduced in ES6?

In case of multiple callbacks, the code will look scary. ES6 comes to your rescue by introducing the concept of promises. Promises are "Continuation events" and they help you execute the multiple async operations together in a much cleaner code style.

What is the use of ES6 promise?

Promises are a way to implement asynchronous programming in JavaScript(ES6 which is also known as ECMAScript-6). A Promise acts as a container for future values. Like if you order any food from any site to deliver it to your place that order record will be the promise and the food will be the value of that promise.

What is Promise library in JavaScript?

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value. To learn about the way promises work and how you can use them, we advise you to read Using promises first.


2 Answers

You should use native promises.

I say that being a maintainer in both Q and Bluebird which you've mentioned. I say this being Bluebird core since 2013 (the start) and advocating Bluebird for several years.

I'll reiterate this is bluebird core telling you not to use bluebird in the browser.

The reason native promises sucked were:

  • They swallowed errors - if you didn't attach a .catch handler the error would be unknown to you. (this has been fixed).
  • They didn't show proper stack traces (this has been fixed).
  • They were slow (this has been largely fixed).

Given these issues were all fixed, and that all browsers implemented promises - you should consider using native promises and async/await over promise libraries as much as possible and to bring helper methods as you see fit.

On the client, promise performance is hardly a bottleneck anyway - and on the server - bluebird is a drop in replacement for when you see a performance issue anyway. There is no reason to use a library like Q or When regardless. If you polyfill native promise - I recommend native-or-bluebird (es6-promise swallows errors last time I checked).

Most of the API advantages bluebird had aren't really relevant anymore - some things (like .some) are still nice, but you should be using async/await for flow control anyway.


When should you use bluebird?

  • Old Node.js (< 8) has really slow promises, there for sure.
  • Really old Node (< 1.3) has promises that swallow errors, there for sure.
  • On browsers that aren't Chrome - native promises are slower - so if you can prove it matters.
  • In older Chrome in order to get async stack traces.
  • If you are writing a library that needs to be compatible with older Node.js versions - for sure.
like image 86
Benjamin Gruenbaum Avatar answered Oct 22 '22 22:10

Benjamin Gruenbaum


Please see @Benjamin Gruenbaum's answer if you are looking for a Promise library to use in the browser.


Available Libraries

First let's look at the most popular Promise libraries available to us.

Library (minified)  | Size*  | Implementation | Native | Client        | Server
---------------------------------------------------------------------------------
native (ES6)        | 0      | Promises/A+    | Yes    | Yes           | Yes
Q                   | 2.5    | Promises/A+    | No     | Yes           | Yes
Bluebird            | 68.4   | Promises/A+    | No     | Bfy*/global   | CommonJS
when                | ?      | Promises/A+    | No     | Yes           | CommonJS
then/promise*       | 4.8    | Promises/A+    | No     | Browserify    | Yes

-

*Size: minified size in KB

*Bfy: Browserify

*Note: es5-shim is required for then/promise if support for < IE9 is required. [source]

*Note: Most libraries support multiple approaches (AMD, Browserify, etc.) for initialisation within in the browser and on the server. This is not an exhaustive list of methods of initialisation.

______

Size

Obviously using the native ES6 implementation is most cost efficient in terms of size as it is embedded in the language and so carries no overhead. The rest should speak for itself. Libraries with extra functionality like Bluebird are relatively large but not large enough that they should prevent you using them, unless space is a major concern.

______

Sustainability

In terms of ongoing development, they are all still being maintained and updated regularly. However this shouldn't be a major concern as the core functionality of all (or perhaps it would be better to say the core APIs that they expose) will remain unchanged.

In terms of completeness: they are all Promises/A+ compliant. That is, they will all behave in the same way. You could use only the functionality given by this specification in any of these libraries, change the library you are using, and the behaviour of your application would remain the same. If you were to use any of the extra functionality provided by any of the individual libraries this would no longer be possible. For example, using Bluebird's many convenience methods would mean your application is 'bound' to the library.

______

'Native-ness'

If this is a requirement, the library best suited would be be no library. That is of course providing that you do not need to support environments which do not implement the ES6 Promise specification. Otherwise, there is no obvious answer. None of these libraries will utilise native Promises if available in the environment - they all implement their own Promise functionality. Which you choose in this regard comes down to the API that you feel most comfortable using. I personally prefer Bluebird as it provides many, many convenience methods and the promisification.

______

Conclusion

You should use whichever library you feel most comfortable with. (In my opinion, regardless of size.) If you require backwards compatibility I recommend avoiding a library that requires a shim and simply using one of the libraries that implements Promises itself. If you need to run Promises in the browser, I suggest adopting a Promise library over using polyfills as they offer functionality that will inevitably become desirable the more you use Promises.

like image 33
sdgluck Avatar answered Oct 22 '22 23:10

sdgluck