Most likelyYes, I already did it, it definitely seems useful.
Edit: My quick-and-dirty but very readable polyfill, based on the above mentioned tutorial:
/**
* minisphere Runtime 1.1b4 - (c) 2015 Fat Cerberus
* A set of system scripts providing advanced, high-level functionality not
* available in the engine itself.
*
* [mini/Promise.js]
* A polyfill for the ES6 Promise object.
**/
Promise = (function(undefined)
{
'use strict';
function Promise(fn)
{
var deferred = [];
var state = 'pending';
var result = undefined;
function handle(handler)
{
if (state == 'pending')
deferred.push(handler);
else {
var callback = state == 'resolved' ? handler.fulfiller
: state == 'rejected' ? handler.rejector
: undefined;
if (typeof callback !== 'function') {
if (state == 'resolved') handler.resolve(result);
if (state == 'rejected') handler.reject(result);
} else if (state == 'rejected') {
handler.reject(callback(result));
} else {
try {
handler.resolve(callback(result));
} catch(e) {
handler.reject(e);
}
}
}
}
function resolve(value)
{
if (state != 'pending') return;
try {
if (value && typeof value.then === 'function') {
value.then(resolve, reject);
return;
}
state = 'resolved';
result = value;
for (var i = 0; i < deferred.length; ++i)
handle(deferred[i]);
deferred = [];
} catch(e) {
reject(e);
}
}
function reject(reason)
{
if (state != 'pending') return;
state = 'rejected'
result = reason;
for (var i = 0; i < deferred.length; ++i)
handle(deferred[i]);
deferred = [];
}
this.catch = function(errback)
{
return this.then(undefined, errback);
};
this.then = function(callback, errback)
{
return new Promise(function(resolve, reject) {
handle({
resolve: resolve, reject: reject,
fulfiller: callback,
rejector: errback
});
});
};
this.done = function(callback, errback)
{
var self = arguments.length > 0 ? this.then.apply(this, arguments) : this;
if (typeof errback !== 'function')
self.catch(function(reason) { throw reason; });
};
fn(resolve, reject);
};
Promise.all = function(iterable)
{
return new Promise(function(resolve, reject) {
var promises = [];
var values = [];
var numPromises = iterable.length;
for (var i = 0; i < numPromises; ++i) {
var v = iterable[i];
if (!v || typeof v.then !== 'function')
v = Promise.resolve(v);
promises.push(v);
v.then(function(value) {
values.push(value);
if (values.length == numPromises)
resolve(values);
}, function(reason) {
reject(reason);
});
}
});
};
Promise.race = function(iterable)
{
return new Promise(function(resolve, reject) {
var numPromises = iterable.length;
for (var i = 0; i < numPromises; ++i) {
var v = iterable[i];
if (!v || typeof v.then !== 'function')
v = Promise.resolve(v);
v.then(function(value) { resolve(value); },
function(reason) { reject(reason); });
}
});
};
Promise.reject = function(reason)
{
return new Promise(function(resolve, reject) {
reject(reason);
});
}
Promise.resolve = function(value)
{
return new Promise(function(resolve, reject) {
resolve(value);
});
}
return Promise;
})();
Edit 2: And me screwing around with it.
This is the kind of thing I do to make sure everything works, and the underlying reason for minisphere's high level of compatibility:
new Promise(function(resolve, reject) {
resolve("the pig ate everything at 8:12");
}).then(function(value) {
Print(value);
return new Promise(function(resolve, reject) {
resolve("the cow ate the pig");
});
}).then(function(value) {
Print(value);
throw new Error("the ape ate the cow");
}).done(function(value) {
Print(value);
}, function(reason) {
Print(reason);
});
Output:
the pig ate everything at 8:12
the cow ate the pig
Error: the ape ate the cow