-
Notifications
You must be signed in to change notification settings - Fork 91
Description
Related to #51.
react-async
is hard to use in legacy ES5 browsers due to the implementation of NeverSettle
class. The problem is subclassing native Promise
is not supported in well-known transpilers, and to achieve this we have to polyfill Reflect
and use custom transpilers.
References:
- babel: Problem with extending Promise babel/babel#1120
- typescript: Proposal: Add new __construct helper for better ES5/ES6 class interop microsoft/TypeScript#15397
Built-in classes such as Date, Array, DOM etc cannot be properly subclassed due to limitations in ES5 (for the transform-classes plugin). You can try to use babel-plugin-transform-builtin-extend based on Object.setPrototypeOf and Reflect.construct, but it also has some limitations.
https://babeljs.io/docs/en/caveats/#classes
Let me show an example:
-
source:
react-async/packages/react-async/src/reducer.js
Lines 3 to 22 in ac09f5f
// This exists to make sure we don't hold any references to user-provided functions class NeverSettle extends Promise { constructor() { super(() => {}, () => {}) /* istanbul ignore next */ if (Object.setPrototypeOf) { // Not available in IE 10, but can be polyfilled Object.setPrototypeOf(this, NeverSettle.prototype) } } finally() { return this } catch() { return this } then() { return this } } -
transpiled (ES5)
var NeverSettle = (function (_super) {
__extends(NeverSettle, _super);
function NeverSettle() {
var _this = _super.call(this, function () { }, function () { }) || this;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^ TypeError: undefined is not a promise
if (Object.setPrototypeOf) {
Object.setPrototypeOf(_this, NeverSettle.prototype);
}
return _this;
}
NeverSettle.prototype.finally = function () {
return this;
};
NeverSettle.prototype.catch = function () {
return this;
};
NeverSettle.prototype.then = function () {
return this;
};
return NeverSettle;
}(Promise));
- simple reproducible code about the error:
Promise.call(this, function () {}, function () {})
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^ TypeError: undefined is not a promise
at Promise (<anonymous>)
So I wish we can change the NeverSettle
implementation rather than force us to set it up that complex setup. For example:
class NeverSettle {
constructor() {
const promise = new Promise(() => {}, () => {});
this.then = promise.then.bind(promise);
this.catch = promise.catch.bind(promise);
this.finally = promise.finally.bind(promise);
}
}