Polyfill Promises A+ spec with the JavaScript library of your choice.
bower install prolyfill
npm install prolyfill
Coming soon...
<script src="https://rawgit.com/pauldijou/prolyfill/master/prolyfill.js"></script>
You want to use Prolyfill
in order to create a spec compliant Promise polyfill. The main difference with other polyfills is that this one does not comes with an implementation. Yep, by its own, it will not be able to do anything. You will have to provide the implementation you want to use to create the polyfill. It's a bit more verbose (but really not much) and it gives you total freedom. The following example use the Q library, but you can use nearly whatever lib you want.
// In the browser, creating a polyfill inside window.Promise if necessary
Prolyfill(window.Q);
// If you want the polyfill but without overriding window.Promise
var Promise = Prolyfill(window.Q, {global: false});
// In Node or using Browserify
var Promise = require('prolyfill')(require('q'));
Important Be sure to set {global: false}
in options so your lib does not write anything inside the global object.
If your library needs to use promises but you know that native support isn't good enough right now and you don't want to impose an implementation to your final users, Prolyfill is exactly what your need! Just ask users what lib they want to use, prolyfill it, and write all your code using the spec syntax.
var Prolyfill = require('prolyfill');
// We are exposing the library as a function accepting at least one attribute
// which is the promise implementation chosen by the final user
return function (lib) {
// Important: notice the option 'global' set to 'false'
// so that Prolyfill does not leak anything inside the global object
// Also, we will use Q as a fallback if no lib is provided
// assure backward compatibility
var Promise = prolyfill(lib || require('q'), {global: false});
// Do your stuff...
};
Want to add another one? Just fill an issue asking for it or directly create a pull request.
Prolifyll
is a function which takes 2 attributes:
- the library you want to use as the polyfill in case the native Promise implementation isn't present.
- some options, as an object, allowing you to customize how you want to render the polyfill. See the following section for more informations about options.
// Really super simple example
Prolyfill(window.RSVP, {fallback: true});
You can override Prolyfill
default options by using Prolyfill.defaults
.
// Now, you will no override window.Promise by default
Prolyfill.defaults.global = false;
You can extend the returned polyfill by using Prolyfill.extend
. See the extend section for more informations about it.
- fallback (default:
true
): if true, Prolyfill will try to use the native Promise if it seems valid enough, otherwise, it will return the polyfilled version of the lib. If false, it will always return the polyfilled version. - global (default:
true
): if true, will write the polyfilled version of the lib inside the global object (ex: insidewindow
for a browser) if there is not already a valid one in it. If you are using Prolyfill inside a library, you should set this option tofalse
since you probably don't want to do anything outside of your scope. - override (default:
false
): if true, Prolyfill will ignore all other options and write the polyfilled version of the lib inside the global object. The only use case for this option is if you want to write code with the Promise A+ spec syntax but not rely on native implementations yet (because bugs, performances, ...) or just want all users to use the same underlying implementation to prevent any surprise. - debug (default:
false
): if true, will try to display a few messages in the console while creating the polyfill
Prolyfill(window.Q);
var promise = new Promise(function (resolve, reject) {
// You can write your code using the spec syntax
// It will use native window.Promise if possible
// Otherwise, it will fallback and use Q
});
promise
.then(function (value) { /* All good! */ })
.catch(functon (reason) { /* Looks like we failed... */ });
This is a super powerful that display a console.log
and resolve a promise after 100ms. At first, it was using Q as promise implementation, but now it will go under a huge refactoring to support any lib and use it to polyfill Promise (meaning it will also try to use the native implementation). The refactoring is fully backward-compatible.
// Before
var Q = require('q');
module.exports = {
doAwesome: function () {
var deferred = Q.defer();
setTimeout(function () {
console.log('I am async dude!');
deferred.resolve(true);
}, 100);
return deferred.promise;
}
};
// After (a bit verbose, but that's backward compatibility for you)
var Q = require('q'), Prolyfill = require('prolyfill');
// Important: notice the option 'global' set to 'false'
// so that Prolyfill does not leak anything inside the global object
var Promise = Prolyfill(Q, {global: false});
function MyAwesomeLib(promiseLib) {
Promise = Prolyfill(promiseLib, {global: false});
return MyAwesomeLib;
}
MyAwesomeLib.doAwesome = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log('I am async dude!');
resolve(true);
}, 100);
});
}
module.exports = MyAwesomeLib;
And for the final user, it will translate to the following:
// Before, when using the lib
require('awesomeLib').doAwesome().then(...);
// After
// Can still do as before and use the default promise lib (here, Q)
require('awesomeLib').doAwesome().then(...);
// Or impose a new promise lib
var bluebird = require('bluebird');
require('awesomeLib')(bluebird).doAwesome().then(...);
Work in progress...
Setup a local environment
npm install
bower install
gulp build:test
Start the test server
gulp serve
Browse the tests at http://localhost:8000/test/build, pick a library and then choose an HTML file to run a set of test based on a particular configuration. Naming convention is [test name]-[configuration name].html
.
- http://localhost:8000/test/build/bluebird/basic-override.html will prolyfill bluebird and run the basic tests (from here) using the override configuration.
- http://localhost:8000/test/build/rsvp/promiseAplus-none.html will prolyfill RSVP and run all Promise A+ test (from here) using the none configuration.
Coming soon...