combine-async-iterators
Advanced tools
Comparing version 1.1.2 to 2.0.0
@@ -1,4 +0,17 @@ | ||
declare function combineAsyncIterators(...iterators: AsyncIterableIterator<any>[]): AsyncIterableIterator<any>; | ||
declare function combineAsyncIterators( | ||
...iterators: AsyncIterableIterator<any>[] | ||
): AsyncIterableIterator<any>; | ||
declare namespace combineAsyncIterators { | ||
interface CombineOptions { | ||
throwError?: boolean; | ||
errorCallback?: (err: Error, index: number) => any; | ||
} | ||
} | ||
declare function combineAsyncIterators( | ||
options: combineAsyncIterators.CombineOptions, | ||
...iterators: AsyncIterableIterator<any>[] | ||
): AsyncIterableIterator<any>; | ||
export = combineAsyncIterators; | ||
50
index.js
"use strict"; | ||
function getNextAsyncIteratorValue(asyncIterator, index) { | ||
return asyncIterator.next().then((iterator) => { | ||
return { index, iterator }; | ||
}); | ||
function getNextAsyncIteratorFactory(options) { | ||
return async(asyncIterator, index) => { | ||
try { | ||
const iterator = await asyncIterator.next(); | ||
return { index, iterator }; | ||
} | ||
catch (err) { | ||
if (options.errorCallback) { | ||
options.errorCallback(err, index); | ||
} | ||
if (options.throwError !== false) { | ||
return Promise.reject(err); | ||
} | ||
return { index, iterator: { done: true } }; | ||
} | ||
}; | ||
} | ||
async function* combineAsyncIterators(...iterators) { | ||
let [options] = iterators; | ||
if (typeof options.next === "function") { | ||
options = Object.create(null); | ||
} | ||
else { | ||
iterators.shift(); | ||
} | ||
// Return if iterators is empty (avoid infinite loop). | ||
@@ -14,27 +36,21 @@ if (iterators.length === 0) { | ||
} | ||
const promiseThatNeverResolve = new Promise(() => null); | ||
const getNextAsyncIteratorValue = getNextAsyncIteratorFactory(options); | ||
try { | ||
const asyncIteratorsValues = iterators.map(getNextAsyncIteratorValue); | ||
let numberOfIteratorsAlive = iterators.length; | ||
const asyncIteratorsValues = new Map(iterators.map((it, idx) => [idx, getNextAsyncIteratorValue(it, idx)])); | ||
do { | ||
const { iterator, index } = await Promise.race(asyncIteratorsValues); | ||
const { iterator, index } = await Promise.race(asyncIteratorsValues.values()); | ||
if (iterator.done) { | ||
numberOfIteratorsAlive--; | ||
// We dont want Promise.race to resolve again on this index | ||
// so we replace it with a Promise that will never resolve. | ||
asyncIteratorsValues[index] = promiseThatNeverResolve; | ||
asyncIteratorsValues.delete(index); | ||
} | ||
else { | ||
yield iterator.value; | ||
asyncIteratorsValues[index] = getNextAsyncIteratorValue(iterators[index], index); | ||
asyncIteratorsValues.set(index, getNextAsyncIteratorValue(iterators[index], index)); | ||
} | ||
} while (numberOfIteratorsAlive > 0); | ||
} while (asyncIteratorsValues.size > 0); | ||
} | ||
catch (err) { | ||
finally { | ||
// TODO: replace .all with .allSettled | ||
await Promise.all(iterators.map((it) => it.return())); | ||
throw err; | ||
} | ||
@@ -41,0 +57,0 @@ } |
{ | ||
"name": "combine-async-iterators", | ||
"version": "1.1.2", | ||
"description": "Combine Multiple Asynchronous Iterators in one (not a sequence)", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test/test.js" | ||
}, | ||
"engines": { | ||
"node": ">=11" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/fraxken/combine-async-iterators.git" | ||
}, | ||
"files": [ | ||
"index.d.ts" | ||
], | ||
"keywords": [ | ||
"async", | ||
"asynchronous", | ||
"iterator", | ||
"iterators", | ||
"iteration", | ||
"iterable", | ||
"combine", | ||
"merge", | ||
"build", | ||
"construct", | ||
"sequence" | ||
], | ||
"author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/fraxken/combine-async-iterators/issues" | ||
}, | ||
"homepage": "https://github.com/fraxken/combine-async-iterators#readme", | ||
"devDependencies": { | ||
"@slimio/eslint-config": "^3.0.3", | ||
"@slimio/is": "^1.5.1", | ||
"@types/node": "^12.6.8", | ||
"japa": "^3.0.1" | ||
} | ||
"name": "combine-async-iterators", | ||
"version": "2.0.0", | ||
"description": "Combine Multiple Asynchronous Iterators in one (not a sequence)", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test/test.js" | ||
}, | ||
"engines": { | ||
"node": ">=11" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/fraxken/combine-async-iterators.git" | ||
}, | ||
"files": [ | ||
"index.d.ts" | ||
], | ||
"keywords": [ | ||
"async", | ||
"asynchronous", | ||
"iterator", | ||
"iterators", | ||
"iteration", | ||
"iterable", | ||
"combine", | ||
"merge", | ||
"build", | ||
"construct", | ||
"sequence" | ||
], | ||
"author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/fraxken/combine-async-iterators/issues" | ||
}, | ||
"homepage": "https://github.com/fraxken/combine-async-iterators#readme", | ||
"devDependencies": { | ||
"@slimio/eslint-config": "^4.1.0", | ||
"@slimio/is": "^1.5.1", | ||
"@types/node": "^14.6.1", | ||
"japa": "^3.1.1", | ||
"sinon": "^9.0.2" | ||
} | ||
} |
@@ -10,2 +10,4 @@ # Combine-async-iterators | ||
> ⚠️ This package was mainly built to work with native Asynchronous Generators (Iterators). | ||
## Requirements | ||
@@ -47,6 +49,36 @@ - [Node.js](https://nodejs.org/en/) version 11 or higher | ||
**Since 2.0.0** it is also possible to recover errors through a callback. By default the method is stopped when an error is thrown (the `throwError` parameter allow to disable this behaviour). | ||
```js | ||
function errorCallback(err) { | ||
console.error("got you:", err); | ||
} | ||
const iteratorOptions = { errorCallback, throwError: false }; | ||
const asyncIterator = combineAsyncIterators(iteratorOptions, getValues("first"), getValues("second")); | ||
for await (const value of asyncIterator) { | ||
console.log(value); | ||
} | ||
``` | ||
## API | ||
```ts | ||
function combineAsyncIterators(...iterators: AsyncIterableIterator<any>[]): AsyncIterableIterator<any> | ||
declare function combineAsyncIterators( | ||
...iterators: AsyncIterableIterator<any>[] | ||
): AsyncIterableIterator<any>; | ||
declare namespace combineAsyncIterators { | ||
interface CombineOptions { | ||
throwError?: boolean; | ||
errorCallback?: (err: Error, index: number) => any; | ||
} | ||
} | ||
declare function combineAsyncIterators( | ||
options: combineAsyncIterators.CombineOptions, | ||
...iterators: AsyncIterableIterator<any>[] | ||
): AsyncIterableIterator<any>; | ||
export = combineAsyncIterators; | ||
``` | ||
@@ -53,0 +85,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7267
64
87
5