diff --git a/@vates/coalesce-calls/README.md b/@vates/coalesce-calls/README.md new file mode 100644 index 000000000..cd52a28b1 --- /dev/null +++ b/@vates/coalesce-calls/README.md @@ -0,0 +1,46 @@ + + +# @vates/coalesce-calls + +[![Package Version](https://badgen.net/npm/v/@vates/coalesce-calls)](https://npmjs.org/package/@vates/coalesce-calls) ![License](https://badgen.net/npm/license/@vates/coalesce-calls) [![PackagePhobia](https://badgen.net/bundlephobia/minzip/@vates/coalesce-calls)](https://bundlephobia.com/result?p=@vates/coalesce-calls) [![Node compatibility](https://badgen.net/npm/node/@vates/coalesce-calls)](https://npmjs.org/package/@vates/coalesce-calls) + +> Wraps an async function so that concurrent calls will be coalesced + +## Install + +Installation of the [npm package](https://npmjs.org/package/@vates/coalesce-calls): + +``` +> npm install --save @vates/coalesce-calls +``` + +## Usage + +```js +import { coalesceCalls } from 'coalesce-calls' + +const connect = coalesceCalls(async function () { + // async operation +}) + +connect() + +// the previous promise result will be returned if the operation is not +// complete yet +connect() +``` + +## Contributions + +Contributions are _very_ welcomed, either on the documentation or on +the code. + +You may: + +- report any [issue](https://github.com/vatesfr/xen-orchestra/issues) + you've encountered; +- fork and create a pull request. + +## License + +[ISC](https://spdx.org/licenses/ISC) © [Vates SAS](https://vates.fr) diff --git a/@vates/coalesce-calls/USAGE.md b/@vates/coalesce-calls/USAGE.md new file mode 100644 index 000000000..110087e2e --- /dev/null +++ b/@vates/coalesce-calls/USAGE.md @@ -0,0 +1,13 @@ +```js +import { coalesceCalls } from 'coalesce-calls' + +const connect = coalesceCalls(async function () { + // async operation +}) + +connect() + +// the previous promise result will be returned if the operation is not +// complete yet +connect() +``` diff --git a/@vates/coalesce-calls/index.js b/@vates/coalesce-calls/index.js new file mode 100644 index 000000000..7999fe76d --- /dev/null +++ b/@vates/coalesce-calls/index.js @@ -0,0 +1,14 @@ +exports.coalesceCalls = function (fn) { + let promise + const clean = () => { + promise = undefined + } + return function () { + if (promise !== undefined) { + return promise + } + promise = fn.apply(this, arguments) + promise.then(clean, clean) + return promise + } +} diff --git a/@vates/coalesce-calls/index.spec.js b/@vates/coalesce-calls/index.spec.js new file mode 100644 index 000000000..7bc9d8e07 --- /dev/null +++ b/@vates/coalesce-calls/index.spec.js @@ -0,0 +1,33 @@ +/* eslint-env jest */ + +const { coalesceCalls } = require('./') + +const pDefer = () => { + const r = {} + r.promise = new Promise((resolve, reject) => { + r.reject = reject + r.resolve = resolve + }) + return r +} + +describe('coalesceCalls', () => { + it('decorates an async function', async () => { + const fn = coalesceCalls(promise => promise) + + const defer1 = pDefer() + const promise1 = fn(defer1.promise) + const defer2 = pDefer() + const promise2 = fn(defer2.promise) + + defer1.resolve('foo') + expect(await promise1).toBe('foo') + expect(await promise2).toBe('foo') + + const defer3 = pDefer() + const promise3 = fn(defer3.promise) + + defer3.resolve('bar') + expect(await promise3).toBe('bar') + }) +}) diff --git a/@vates/coalesce-calls/package.json b/@vates/coalesce-calls/package.json new file mode 100644 index 000000000..4c165fb53 --- /dev/null +++ b/@vates/coalesce-calls/package.json @@ -0,0 +1,38 @@ +{ + "private": false, + "name": "@vates/coalesce-calls", + "description": "Wraps an async function so that concurrent calls will be coalesced", + "keywords": [ + "async", + "calls", + "coalesce", + "decorate", + "decorator", + "merge", + "promise", + "wrap", + "wrapper" + ], + "homepage": "https://github.com/vatesfr/xen-orchestra/tree/master/@vates/coalesce-calls", + "bugs": "https://github.com/vatesfr/xen-orchestra/issues", + "repository": { + "directory": "@vates/coalesce-calls", + "type": "git", + "url": "https://github.com/vatesfr/xen-orchestra.git" + }, + "files": [ + "index.js" + ], + "author": { + "name": "Vates SAS", + "url": "https://vates.fr" + }, + "license": "ISC", + "version": "0.1.0", + "engines": { + "node": ">=8.10" + }, + "scripts": { + "postversion": "npm publish --access public" + } +}