diff --git a/index.d.ts b/index.d.ts index 9a60f93..b552f78 100644 --- a/index.d.ts +++ b/index.d.ts @@ -315,6 +315,21 @@ interface ThenPromiseConstructor { */ race(values: (T | PromiseLike)[]): ThenPromise; + /** + * Takes a callback of any kind (returns or throws, synchronously or asynchronously) and wraps its result + * in a Promise. + * + * @param callbackFn A function that is called synchronously. It can do anything: either return + * a value, throw an error, or return a promise. + * @param args Additional arguments, that will be passed to the callback. + * + * @returns A Promise that is: + * - Already fulfilled, if the callback synchronously returns a value. + * - Already rejected, if the callback synchronously throws an error. + * - Asynchronously fulfilled or rejected, if the callback returns a promise. + */ + try(callbackFn: (...args: U) => T | PromiseLike, ...args: U): Promise>; + /** * Creates a new rejected promise for the provided reason. * @param reason The reason the promise was rejected. diff --git a/package.json b/package.json index 4895a1f..7217c06 100644 --- a/package.json +++ b/package.json @@ -25,11 +25,11 @@ "acorn": "^1.0.1", "better-assert": "*", "istanbul": "^0.3.13", - "mocha": "*", + "mocha": "^10.8.2", "promises-aplus-tests": "*", "rimraf": "^2.3.2" }, "dependencies": { "asap": "~2.0.6" } -} \ No newline at end of file +} diff --git a/src/es6-extensions.js b/src/es6-extensions.js index f3e6198..4b7b21b 100644 --- a/src/es6-extensions.js +++ b/src/es6-extensions.js @@ -154,6 +154,13 @@ function getAggregateError(errors){ return error; } +Promise.try = function promiseTry(callbackFn) { + var args = arguments; + return new Promise(function (resolve) { + resolve(callbackFn.apply(undefined, iterableToArray(args).slice(1))); + }); +}; + Promise.any = function promiseAny(values) { return new Promise(function(resolve, reject) { var promises = iterableToArray(values); diff --git a/test/extensions-tests.js b/test/extensions-tests.js index f38485a..4fdff24 100644 --- a/test/extensions-tests.js +++ b/test/extensions-tests.js @@ -130,6 +130,79 @@ describe('extensions', function () { }) }) }) + describe('Promise.try', function () { + describe('invalid arguments', function () { + it("rejects when no function is given", function (done) { + Promise.try().catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + it("rejects when pass null as function", function (done) { + Promise.try(null).catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + it("rejects when pass non-function as function", function (done) { + Promise.try(123).catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + it("rejects when pass object as function", function (done) { + Promise.try({}).catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + it("rejects when pass array as function", function (done) { + Promise.try([]).catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + it("rejects when pass string as function", function (done) { + Promise.try("test").catch(function (err) { + assert(err instanceof Error) + }).nodeify(done) + }) + }); + describe('resolve/reject', function () { + it("resolves when function returns a value", function (done) { + Promise.try(function () { + return sentinel + }).then(function (res) { + assert(res === sentinel) + }).nodeify(done) + }) + it("resolves when function returns a promise", function (done) { + Promise.try(function () { + return Promise.resolve(sentinel) + }).then(function (res) { + assert(res === sentinel) + }).nodeify(done) + }) + it("rejects when function throws an error", function (done) { + Promise.try(function () { + throw sentinel + }).catch(function (err) { + assert(err === sentinel) + }).nodeify(done) + }) + it("rejects when function returns a rejected promise", function (done) { + Promise.try(function () { + return Promise.reject(sentinel) + }).catch(function (err) { + assert(err === sentinel) + }).nodeify(done) + }) + }) + describe('arguments mapping', function () { + it("passes the arguments to the function", function (done) { + Promise.try(function (a, b, c) { + assert(a === 1) + assert(b === 2) + assert(c === 3) + }, 1, 2, 3).nodeify(done) + }) + }) + }); describe('Promise.any(...)', function () { describe('an array', function () { describe('that is empty', function () {