synchronous-promise
Advanced tools
Comparing version 2.0.13 to 2.0.14
@@ -6,5 +6,7 @@ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
"use strict"; | ||
function makeArrayFrom(obj) { | ||
return Array.prototype.slice.apply(obj); | ||
} | ||
var | ||
@@ -84,4 +86,5 @@ PENDING = "pending", | ||
}, | ||
finally: function(callback) { | ||
finally: function (callback) { | ||
var ran = false; | ||
function runFinally(result, err) { | ||
@@ -95,3 +98,3 @@ if (!ran) { | ||
if (looksLikeAPromise(callbackResult)) { | ||
return callbackResult.then(function() { | ||
return callbackResult.then(function () { | ||
if (err) { | ||
@@ -107,7 +110,8 @@ throw err; | ||
} | ||
return this | ||
.then(function(result) { | ||
.then(function (result) { | ||
return runFinally(result); | ||
}) | ||
.catch(function(err) { | ||
.catch(function (err) { | ||
return runFinally(null, err); | ||
@@ -356,2 +360,75 @@ }); | ||
SynchronousPromise.any = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.reject({ errors: [] }); | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allErrors = [], | ||
numRejected = 0, | ||
doReject = function () { | ||
if (numRejected === args.length) { | ||
reject({ errors: allErrors }); | ||
} | ||
}, | ||
resolved = false, | ||
doResolve = function (result) { | ||
if (resolved) { | ||
return; | ||
} | ||
resolved = true; | ||
resolve(result); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
doResolve(thisResult); | ||
}).catch(function (err) { | ||
allErrors[idx] = err; | ||
numRejected += 1; | ||
doReject(); | ||
}); | ||
}); | ||
}); | ||
}; | ||
SynchronousPromise.allSettled = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
return new SynchronousPromise(function (resolve) { | ||
var | ||
allData = [], | ||
numSettled = 0, | ||
doSettled = function () { | ||
numSettled += 1; | ||
if (numSettled === args.length) { | ||
resolve(allData); | ||
} | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = { | ||
status: "fulfilled", | ||
value: thisResult | ||
}; | ||
doSettled(); | ||
}).catch(function (err) { | ||
allData[idx] = { | ||
status: "rejected", | ||
reason: err | ||
}; | ||
doSettled(); | ||
}); | ||
}); | ||
}); | ||
}; | ||
/* jshint ignore:start */ | ||
@@ -362,3 +439,3 @@ if (Promise === SynchronousPromise) { | ||
var RealPromise = Promise; | ||
SynchronousPromise.installGlobally = function(__awaiter) { | ||
SynchronousPromise.installGlobally = function (__awaiter) { | ||
if (Promise === SynchronousPromise) { | ||
@@ -372,3 +449,3 @@ return __awaiter; | ||
SynchronousPromise.uninstallGlobally = function() { | ||
SynchronousPromise.uninstallGlobally = function () { | ||
if (Promise === SynchronousPromise) { | ||
@@ -380,7 +457,7 @@ Promise = RealPromise; | ||
function patchAwaiterIfRequired(__awaiter) { | ||
if (typeof(__awaiter) === "undefined" || __awaiter.__patched) { | ||
if (typeof (__awaiter) === "undefined" || __awaiter.__patched) { | ||
return __awaiter; | ||
} | ||
var originalAwaiter = __awaiter; | ||
__awaiter = function() { | ||
__awaiter = function () { | ||
var Promise = RealPromise; | ||
@@ -392,2 +469,3 @@ originalAwaiter.apply(this, makeArrayFrom(arguments)); | ||
} | ||
/* jshint ignore:end */ | ||
@@ -394,0 +472,0 @@ |
@@ -7,2 +7,12 @@ export interface SynchronousPromise<T> extends Promise<T> { | ||
export type ValueOrPromiseOfValue<T> = T | PromiseLike<T> | ||
export type RejectedOutcome = { | ||
status: "rejected", | ||
reason: any | ||
} | ||
export type FulfilledOutcome<T> = { | ||
status: "fulfilled", | ||
value: T | ||
} | ||
export type SettledOutcome<T> = FulfilledOutcome<T> | RejectedOutcome | ||
export interface SynchronousPromiseConstructor { | ||
@@ -25,9 +35,32 @@ /** | ||
* resolve, or rejected when any Promise is rejected. | ||
* @param values An array of Promises. | ||
* @param v1 An array of Promises | ||
* @returns A new Promise. | ||
*/ | ||
all<T>(v1: ValueOrPromiseOfValue<T>[]): SynchronousPromise<T[]>; | ||
all<TAll>(...values: ValueOrPromiseOfValue<TAll>[]): SynchronousPromise<TAll[]>; | ||
/** | ||
* Creates a Promise that is resolved with an array of results when all of the provided Promises | ||
* resolve, or rejected when any Promise is rejected. | ||
* @param values Any number of Promises. | ||
* @returns A new Promise. | ||
*/ | ||
all<T>(...values: ValueOrPromiseOfValue<T>[]): SynchronousPromise<T[]>; | ||
/** | ||
* Creates a Promise that is resolved with an array of outcome objects after all of the provided Promises | ||
* have settled. Each outcome object has a .status of either "fulfilled" or "rejected" and corresponding | ||
* "value" or "reason" properties. | ||
* @param v1 An array of Promises. | ||
* @returns A new Promise. | ||
*/ | ||
allSettled<T>(v1: ValueOrPromiseOfValue<T>[]): SynchronousPromise<SettledOutcome<T>[]>; | ||
/** | ||
* Creates a Promise that is resolved with an array of outcome objects after all of the provided Promises | ||
* have settled. Each outcome object has a .status of either "fulfilled" or "rejected" and corresponding | ||
* "value" or "reason" properties. | ||
* @param values Any number of promises | ||
* @returns A new Promise. | ||
*/ | ||
allSettled<TAllSettled>(...values: ValueOrPromiseOfValue<TAllSettled>[]): SynchronousPromise<SettledOutcome<TAllSettled>[]>; | ||
/** | ||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved | ||
@@ -41,2 +74,15 @@ * or rejected. | ||
/** | ||
* Creates a Promise that is resolved with the first value from the provided | ||
* Promises, or rejected when all provided Promises reject | ||
* @param v1 An array of Promises | ||
*/ | ||
any<T>(v1: ValueOrPromiseOfValue<T>[]): SynchronousPromise<T>; | ||
/** | ||
* Creates a Promise that is resolved with the first value from the provided | ||
* Promises, or rejected when all provided Promises reject | ||
* @param values Any number of Promises | ||
*/ | ||
any<T>(...values: ValueOrPromiseOfValue<T>[]): SynchronousPromise<T>; | ||
/** | ||
* Creates a new rejected promise for the provided reason. | ||
@@ -76,3 +122,3 @@ * @param reason The reason the promise was rejected. | ||
/** | ||
* Installs SynchronousPromise as the global Promise implementation. | ||
* Installs SynchronousPromise as the global Promise implementation. | ||
* When running from within typescript, you will need to use this to | ||
@@ -79,0 +125,0 @@ * patch the generated __awaiter to ensure it gets a _real_ Promise implementation |
94
index.js
/* jshint node: true */ | ||
"use strict"; | ||
function makeArrayFrom(obj) { | ||
return Array.prototype.slice.apply(obj); | ||
} | ||
var | ||
@@ -80,4 +82,5 @@ PENDING = "pending", | ||
}, | ||
finally: function(callback) { | ||
finally: function (callback) { | ||
var ran = false; | ||
function runFinally(result, err) { | ||
@@ -91,3 +94,3 @@ if (!ran) { | ||
if (looksLikeAPromise(callbackResult)) { | ||
return callbackResult.then(function() { | ||
return callbackResult.then(function () { | ||
if (err) { | ||
@@ -103,7 +106,8 @@ throw err; | ||
} | ||
return this | ||
.then(function(result) { | ||
.then(function (result) { | ||
return runFinally(result); | ||
}) | ||
.catch(function(err) { | ||
.catch(function (err) { | ||
return runFinally(null, err); | ||
@@ -352,2 +356,75 @@ }); | ||
SynchronousPromise.any = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.reject({ errors: [] }); | ||
} | ||
return new SynchronousPromise(function (resolve, reject) { | ||
var | ||
allErrors = [], | ||
numRejected = 0, | ||
doReject = function () { | ||
if (numRejected === args.length) { | ||
reject({ errors: allErrors }); | ||
} | ||
}, | ||
resolved = false, | ||
doResolve = function (result) { | ||
if (resolved) { | ||
return; | ||
} | ||
resolved = true; | ||
resolve(result); | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
doResolve(thisResult); | ||
}).catch(function (err) { | ||
allErrors[idx] = err; | ||
numRejected += 1; | ||
doReject(); | ||
}); | ||
}); | ||
}); | ||
}; | ||
SynchronousPromise.allSettled = function () { | ||
var args = makeArrayFrom(arguments); | ||
if (Array.isArray(args[0])) { | ||
args = args[0]; | ||
} | ||
if (!args.length) { | ||
return SynchronousPromise.resolve([]); | ||
} | ||
return new SynchronousPromise(function (resolve) { | ||
var | ||
allData = [], | ||
numSettled = 0, | ||
doSettled = function () { | ||
numSettled += 1; | ||
if (numSettled === args.length) { | ||
resolve(allData); | ||
} | ||
}; | ||
args.forEach(function (arg, idx) { | ||
SynchronousPromise.resolve(arg).then(function (thisResult) { | ||
allData[idx] = { | ||
status: "fulfilled", | ||
value: thisResult | ||
}; | ||
doSettled(); | ||
}).catch(function (err) { | ||
allData[idx] = { | ||
status: "rejected", | ||
reason: err | ||
}; | ||
doSettled(); | ||
}); | ||
}); | ||
}); | ||
}; | ||
/* jshint ignore:start */ | ||
@@ -358,3 +435,3 @@ if (Promise === SynchronousPromise) { | ||
var RealPromise = Promise; | ||
SynchronousPromise.installGlobally = function(__awaiter) { | ||
SynchronousPromise.installGlobally = function (__awaiter) { | ||
if (Promise === SynchronousPromise) { | ||
@@ -368,3 +445,3 @@ return __awaiter; | ||
SynchronousPromise.uninstallGlobally = function() { | ||
SynchronousPromise.uninstallGlobally = function () { | ||
if (Promise === SynchronousPromise) { | ||
@@ -376,7 +453,7 @@ Promise = RealPromise; | ||
function patchAwaiterIfRequired(__awaiter) { | ||
if (typeof(__awaiter) === "undefined" || __awaiter.__patched) { | ||
if (typeof (__awaiter) === "undefined" || __awaiter.__patched) { | ||
return __awaiter; | ||
} | ||
var originalAwaiter = __awaiter; | ||
__awaiter = function() { | ||
__awaiter = function () { | ||
var Promise = RealPromise; | ||
@@ -388,2 +465,3 @@ originalAwaiter.apply(this, makeArrayFrom(arguments)); | ||
} | ||
/* jshint ignore:end */ | ||
@@ -390,0 +468,0 @@ |
@@ -764,2 +764,223 @@ /* | ||
}); | ||
describe("static any", function () { | ||
it("should be a function", function () { | ||
expect(SynchronousPromise.any).to.be.a("function") | ||
}); | ||
it("should resolve with first value from given resolved promises as variable args", function () { | ||
const p1 = createResolved("abc"), | ||
p2 = createResolved("123"), | ||
any = SynchronousPromise.any(p1, p2); | ||
let captured = null; | ||
any.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.equal("abc"); | ||
}); | ||
it("should resolve with first value from given promise or none promise variable args", function () { | ||
const any = SynchronousPromise.any(["123", createResolved("abc")]); | ||
let captured = null; | ||
any.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.equal("123"); | ||
}); | ||
it("should reject empty promise array", function () { | ||
const any = SynchronousPromise.any([]); | ||
let capturedData = null, | ||
capturedError = null; | ||
any.then(function (data) { | ||
capturedData = data; | ||
}, function (err) { | ||
capturedError = err; | ||
}); | ||
expect(capturedData).to.be.null; | ||
expect(capturedError).to.have.property("errors"); | ||
expect(capturedError).property("errors").to.have.length(0); | ||
}); | ||
it("should resolve if any promise resolves", function () { | ||
const p1 = createResolved("abc"), | ||
p2 = createRejected("123"), | ||
any = SynchronousPromise.any(p1, p2); | ||
let capturedData = null, | ||
capturedError = null; | ||
any.then(function (data) { | ||
capturedData = data; | ||
}).catch(function (err) { | ||
capturedError = err; | ||
}); | ||
expect(capturedData).to.equal("abc"); | ||
expect(capturedError).to.be.null; | ||
}); | ||
it("should reject if all promises reject", function () { | ||
const p1 = createRejected("abc"), | ||
p2 = createRejected("123"), | ||
any = SynchronousPromise.any(p1, p2); | ||
let capturedData = null, | ||
capturedError = null; | ||
any.then(function (data) { | ||
capturedData = data; | ||
}).catch(function (err) { | ||
capturedError = err; | ||
}); | ||
expect(capturedData).to.be.null; | ||
expect(capturedError).to.have.property("errors"); | ||
expect(capturedError).property("errors").to.have.length(2); | ||
expect(capturedError).property("errors").to.contain("abc"); | ||
expect(capturedError).property("errors").to.contain("123"); | ||
}); | ||
it("should reject with values in the correct order", function () { | ||
let reject1 = undefined, | ||
reject2 = undefined, | ||
capturedError = undefined; | ||
const p1 = create(function (resolve, reject) { | ||
reject1 = reject; | ||
}); | ||
const p2 = create(function (resolve, reject) { | ||
reject2 = reject; | ||
}); | ||
SynchronousPromise.any([p1, p2]).catch(function (data) { | ||
capturedError = data; | ||
}); | ||
reject2("a"); | ||
reject1("b"); | ||
expect(capturedError).to.have.property("errors"); | ||
expect(capturedError).property("errors").to.deep.equal(["b", "a"]); | ||
}); | ||
}); | ||
describe("static allSettled", function () { | ||
it("should be a function", function () { | ||
expect(SynchronousPromise.allSettled).to.be.a("function") | ||
}); | ||
it("should resolve with all values from given resolved promises as variable args", function () { | ||
const p1 = createResolved("abc"), | ||
p2 = createResolved("123"), | ||
allSettled = SynchronousPromise.allSettled(p1, p2); | ||
let captured = null; | ||
allSettled.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.have.length(2); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "abc" }); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "123" }); | ||
}); | ||
it("should resolve with all values from given rejected promises as variable args", function () { | ||
const error1 = new Error("error1"); | ||
const error2 = new Error("error2"); | ||
const p1 = createRejected(error1), | ||
p2 = createRejected(error2), | ||
allSettled = SynchronousPromise.allSettled(p1, p2); | ||
let captured = null; | ||
allSettled.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.have.length(2); | ||
expect(captured).to.deep.contain({ status: "rejected", reason: error1 }); | ||
expect(captured).to.deep.contain({ status: "rejected", reason: error2 }); | ||
}); | ||
it("should resolve with all values from given promise or none promise variable args", function () { | ||
const allSettled = SynchronousPromise.allSettled(["123", createResolved("abc")]); | ||
let captured = null; | ||
allSettled.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.have.length(2); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "abc" }); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "123" }); | ||
}); | ||
it("should resolve with all values from given resolved promises as an array", function () { | ||
const p1 = createResolved("abc"), | ||
p2 = createResolved("123"), | ||
allSettled = SynchronousPromise.allSettled([p1, p2]); | ||
let captured = null; | ||
allSettled.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.have.length(2); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "abc" }); | ||
expect(captured).to.deep.contain({ status: "fulfilled", value: "123" }); | ||
}); | ||
it("should resolve empty promise array", function () { | ||
const allSettled = SynchronousPromise.allSettled([]); | ||
let captured = null; | ||
allSettled.then(function (data) { | ||
captured = data; | ||
}); | ||
expect(captured).to.have.length(0); | ||
}); | ||
it("should resolve with values in the correct order", function () { | ||
let resolve1 = undefined, | ||
resolve2 = undefined, | ||
captured = undefined; | ||
const p1 = create(function (resolve) { | ||
resolve1 = resolve; | ||
}); | ||
const p2 = create(function (resolve) { | ||
resolve2 = resolve; | ||
}); | ||
SynchronousPromise.allSettled([p1, p2]).then(function (data) { | ||
captured = data; | ||
}); | ||
resolve2("a"); | ||
resolve1("b"); | ||
expect(captured).to.deep.equal([ | ||
{ status: "fulfilled", value: "b" }, | ||
{ status: "fulfilled", value: "a" } | ||
]); | ||
}); | ||
it("should only resolve after all promises are settled", function () { | ||
const p1 = createResolved("abc"), | ||
p2 = createRejected("123"), | ||
allSettled = SynchronousPromise.allSettled(p1, p2); | ||
let capturedData = null; | ||
allSettled.then(function (data) { | ||
capturedData = data; | ||
}); | ||
expect(capturedData).to.have.length(2); | ||
}); | ||
}); | ||
describe("static unresolved", function () { | ||
@@ -766,0 +987,0 @@ it("should exist as a function", function () { |
{ | ||
"name": "synchronous-promise", | ||
"version": "2.0.13", | ||
"version": "2.0.14", | ||
"description": "Synchronous Promise-like prototype to use in testing where you would have used an ES6 Promise", | ||
@@ -36,17 +36,17 @@ "main": "index.js", | ||
"devDependencies": { | ||
"@types/chai": "^4.1.5", | ||
"@types/mocha": "^2.2.44", | ||
"@types/node": "^8.10.30", | ||
"browserify": "^14.5.0", | ||
"chai": "^4.1.2", | ||
"jshint": "^2.9.6", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^4.0.1", | ||
"mocha-yar": "^1.0.13", | ||
"nodemon": "^1.18.4", | ||
"npm-run-all": "^4.1.2", | ||
"run-sequence": "^2.2.0", | ||
"ts-node": "^3.3.0", | ||
"typescript": "^2.9.2" | ||
"@types/chai": "^4.2.11", | ||
"@types/mocha": "^7.0.2", | ||
"@types/node": "^14.0.5", | ||
"browserify": "^16.5.1", | ||
"chai": "^4.2.0", | ||
"jshint": "^2.11.1", | ||
"mkdirp": "^1.0.4", | ||
"mocha": "^7.1.2", | ||
"mocha-yar": "^1.0.14", | ||
"nodemon": "^2.0.4", | ||
"npm-run-all": "^4.1.5", | ||
"run-sequence": "^2.2.1", | ||
"ts-node": "^8.10.1", | ||
"typescript": "^3.9.3" | ||
} | ||
} |
@@ -10,2 +10,4 @@ # synchronous-promise | ||
![npm](https://img.shields.io/npm/v/synchronous-promise) | ||
### Why? | ||
@@ -12,0 +14,0 @@ The standard ES6 Promise (and any others which *are* A+ compliant) push the promise logic to the background |
106376
2646
298