diff --git a/index.js b/index.js index a6b57ea7..0919764e 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ module.exports = { math: require("./math"), number: require("./number"), object: require("./object"), + promise: require("./promise"), regExp: require("./reg-exp"), string: require("./string") }; diff --git a/promise/.eslintrc.json b/promise/.eslintrc.json new file mode 100644 index 00000000..fd5e0e9d --- /dev/null +++ b/promise/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "globals": { "Promise": true } +} diff --git a/promise/index.js b/promise/index.js new file mode 100644 index 00000000..33ad830c --- /dev/null +++ b/promise/index.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + lazy: require("./lazy") +}; diff --git a/promise/lazy.js b/promise/lazy.js new file mode 100644 index 00000000..9611ef1d --- /dev/null +++ b/promise/lazy.js @@ -0,0 +1,38 @@ +"use strict"; + +var isFunction = require("../function/is-function"); + +module.exports = function (executor) { + var Constructor; + if (isFunction(this)) { + Constructor = this; + } else if (typeof Promise === "function") { + Constructor = Promise; + } else { + throw new TypeError("Could not resolve Promise constuctor"); + } + + var lazyThen; + var promise = new Constructor(function (resolve, reject) { + lazyThen = function (onSuccess, onFailure) { + if (!hasOwnProperty.call(this, "then")) { + // Sanity check + throw new Error("Unexpected (inherited) lazy then invocation"); + } + + try { + executor(resolve, reject); + } catch (reason) { + reject(reason); + } + delete this.then; + return this.then(onSuccess, onFailure); + }; + }); + + return Object.defineProperty(promise, "then", { + configurable: true, + writable: true, + value: lazyThen + }); +}; diff --git a/test/promise/.eslintrc.json b/test/promise/.eslintrc.json new file mode 100644 index 00000000..46c84236 --- /dev/null +++ b/test/promise/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "globals": { "setTimeout": true } +} diff --git a/test/promise/lazy.js b/test/promise/lazy.js new file mode 100644 index 00000000..8c7a5bfa --- /dev/null +++ b/test/promise/lazy.js @@ -0,0 +1,52 @@ +"use strict"; + +module.exports = function (t) { + if (typeof Promise !== "function") return null; // Run tests only in ES2015+ env + + return { + "Delays execution": function (a, d) { + var invoked = false; + var promise = t(function (resolve) { + invoked = true; + setTimeout(function () { + resolve(20); + }, 10); + }); + + a(invoked, false); + + setTimeout(function () { + a(invoked, false); + promise.then(function (value) { + a(value, 20); + setTimeout(d, 0); // Escape error swallowing + }); + a(invoked, true); + }, 15); + }, + "Passes rejection": function (a, d) { + var promise = t(function (resolve, reject) { + setTimeout(function () { + reject(new Error("Stop")); + }, 10); + }); + + promise.catch(function (error) { + a(error instanceof Error, true); + a(error.message, "Stop"); + setTimeout(d, 0); // Escape error swallowing + }); + }, + "Passes sync exception": function (a, d) { + var promise = t(function () { + throw new Error("Stop"); + }); + + promise.catch(function (error) { + a(error instanceof Error, true); + a(error.message, "Stop"); + setTimeout(d, 0); // Escape error swallowing + }); + } + }; +};