mergeiterator
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -15,36 +15,48 @@ "use strict"; | ||
var getIterator = function getIterator(iterable) { | ||
return iterable[Symbol.asyncIterator] ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); | ||
return typeof iterable[Symbol.asyncIterator] === "function" ? iterable[Symbol.asyncIterator]() : typeof iterable[Symbol.iterator] === "function" ? iterable[Symbol.iterator]() : typeof iterable.next === "function" ? iterable : iterable[Symbol.asyncIterator](); | ||
}; | ||
var resolveDone = function resolveDone(value) { | ||
return { value: value, done: true }; | ||
}; | ||
var resolveNotDone = function resolveNotDone(value) { | ||
return { value: value, done: false }; | ||
}; | ||
var resolveRecord = function resolveRecord(_ref) { | ||
var value = _ref.value, | ||
done = _ref.done; | ||
return Promise.resolve(value).then(done ? resolveDone : resolveNotDone); | ||
}; | ||
var resolveThenable = function resolveThenable(promise) { | ||
return Promise.resolve(promise).then(resolveRecord); | ||
}; | ||
function merge(sequences) { | ||
return _defineProperty({}, Symbol.asyncIterator, function () { | ||
var sequenceIterator = getIterator(sequences); | ||
var ticks = []; | ||
var results = []; | ||
var resolvers = []; | ||
var returns = []; | ||
var count = 0; | ||
var remainingIterators = 1; | ||
var abortionResult = null; | ||
var resolveAbortion = null; | ||
var _iterator; | ||
function pushResult(promise) { | ||
if (resolvers.length > 0) { | ||
resolvers.shift()(promise); | ||
} else { | ||
results.push(promise); | ||
} | ||
var sequenceIterator = getIterator(sequences); | ||
var ticks = []; | ||
var results = []; | ||
var resolvers = []; | ||
var returnedValues = []; | ||
var mergeResult = { value: returnedValues, done: true }; | ||
var mergeResover = void 0, | ||
mergePromise = new Promise(function (resolve) { | ||
return mergeResover = resolve; | ||
}); | ||
var inputClosed = false; | ||
var outputClosed = false; | ||
var count = 0; | ||
var remainingIterators = 1; | ||
function copyResults() { | ||
while (!outputClosed && resolvers.length > 0 && results.length > 0) { | ||
resolvers.shift()(results.shift()); | ||
} | ||
function pushNext(next, abort) { | ||
if (resolveAbortion && resolvers.length === 0) { | ||
abort(); | ||
} else if (resolvers.length > 0 && ticks.length === 0) { | ||
next(); | ||
} else { | ||
ticks.push(next); | ||
if (inputClosed || outputClosed) { | ||
while (resolvers.length > 0) { | ||
resolvers.shift()({ value: undefined, done: true }); | ||
} | ||
} | ||
function runTicks() { | ||
if (resolvers.length > 0 || inputClosed || outputClosed) { | ||
while (ticks.length) { | ||
@@ -54,103 +66,132 @@ ticks.shift()(); | ||
} | ||
} | ||
function iteratorFinished() { | ||
--remainingIterators; | ||
if (remainingIterators === 0) { | ||
pushResult({ value: returns, done: true }); | ||
while (resolvers.length) { | ||
pushResult({ value: undefined, done: true }); | ||
} | ||
if (resolveAbortion) { | ||
resolveAbortion(abortionResult); | ||
} else { | ||
resolveAbortion = function resolveAbortion() {}; | ||
} | ||
} | ||
function pushResult(promise) { | ||
if (!inputClosed) { | ||
results.push(promise); | ||
} | ||
} | ||
function closeIterator(iterator, returnIndex) { | ||
Promise.resolve(iterator.return()).then(function (_ref) { | ||
var value = _ref.value, | ||
done = _ref.done; | ||
function pushNext(next, abort) { | ||
if (!inputClosed) { | ||
ticks.push(next); | ||
} else { | ||
abort(); | ||
} | ||
} | ||
function iteratorFinished() { | ||
--remainingIterators; | ||
if (remainingIterators === 0) { | ||
pushResult(mergeResult); | ||
close(); | ||
mergeResover(mergeResult); | ||
} | ||
} | ||
function closeIterator(iterator, returnIndex) { | ||
if (typeof iterator.return === "function") { | ||
resolveThenable(iterator.return()).then(function (_ref2) { | ||
var value = _ref2.value, | ||
done = _ref2.done; | ||
if (done) { | ||
returns[returnIndex] = value; | ||
returnedValues[returnIndex] = value; | ||
} | ||
}, function (error) { | ||
abortionResult = Promise.reject(error); | ||
mergeResult = Promise.reject(error); | ||
}).then(iteratorFinished); | ||
} else { | ||
iteratorFinished(); | ||
} | ||
} | ||
function closeSeq() { | ||
closeIterator(sequenceIterator, "value"); | ||
} | ||
function closeSeq() { | ||
closeIterator(sequenceIterator, "value"); | ||
} | ||
ticks.push(function nextSeq() { | ||
var sequencePromise = Promise.resolve(sequenceIterator.next()); | ||
sequencePromise.then(function onSequenceResolve(_ref2) { | ||
var value = _ref2.value, | ||
done = _ref2.done; | ||
function nextSeq() { | ||
var sequencePromise = resolveThenable(sequenceIterator.next()); | ||
sequencePromise.then(function onSequenceResolve(_ref3) { | ||
var value = _ref3.value, | ||
done = _ref3.done; | ||
if (done) { | ||
returns.value = value; | ||
iteratorFinished(); | ||
} else { | ||
var closeValue = function closeValue() { | ||
closeIterator(valueIterator, index); | ||
}; | ||
if (done) { | ||
returnedValues.value = value; | ||
iteratorFinished(); | ||
} else { | ||
var closeValue = function closeValue() { | ||
closeIterator(valueIterator, index); | ||
}; | ||
++remainingIterators; | ||
var index = count++; | ||
var valueIterator = getIterator(value); | ||
var nextValue = function nextValue() { | ||
var valuePromise = resolveThenable(valueIterator.next()); | ||
valuePromise.then(function onValueResolve(_ref4) { | ||
var value = _ref4.value, | ||
done = _ref4.done; | ||
void function nextValue() { | ||
var valuePromise = Promise.resolve(valueIterator.next()); | ||
valuePromise.then(function onValueResolve(_ref3) { | ||
var value = _ref3.value, | ||
done = _ref3.done; | ||
if (done) { | ||
returns[index] = value; | ||
iteratorFinished(); | ||
} else { | ||
pushResult(valuePromise); | ||
pushNext(nextValue, closeValue); | ||
} | ||
}, function onValueReject() { | ||
if (done) { | ||
returnedValues[index] = value; | ||
iteratorFinished(); | ||
} else { | ||
pushResult(valuePromise); | ||
pushNext(nextValue, closeValue); | ||
}); | ||
}(); | ||
copyResults(); | ||
} | ||
}, function onValueReject() { | ||
pushResult(valuePromise); | ||
close(); | ||
}); | ||
}; | ||
pushNext(nextSeq, closeSeq); | ||
} | ||
}, function onSequenceReject() { | ||
pushResult(sequencePromise); | ||
++remainingIterators; | ||
var index = count++; | ||
var valueIterator = getIterator(value); | ||
nextValue(); | ||
pushNext(nextSeq, closeSeq); | ||
}); | ||
copyResults(); | ||
} | ||
}, function onSequenceReject() { | ||
pushResult(sequencePromise); | ||
close(); | ||
}); | ||
} | ||
return { | ||
next: function next() { | ||
return new Promise(function (resolve) { | ||
if (resolveAbortion) { | ||
resolve({ value: undefined, done: true }); | ||
} else if (results.length > 0) { | ||
resolve(results.shift()); | ||
} else { | ||
resolvers.push(resolve); | ||
runTicks(); | ||
} | ||
function close() { | ||
inputClosed = true; | ||
copyResults(); | ||
} | ||
ticks.push(nextSeq); | ||
var iterator = (_iterator = {}, _defineProperty(_iterator, Symbol.asyncIterator, function () { | ||
return iterator; | ||
}), _defineProperty(_iterator, "next", function next() { | ||
return new Promise(function (resolve) { | ||
resolvers.push(resolve); | ||
copyResults(); | ||
}); | ||
}), _defineProperty(_iterator, "return", function _return(value) { | ||
return new Promise(function (resolve) { | ||
if (resolvers.length === 0) { | ||
finish(); | ||
} else { | ||
var last = resolvers.pop(); | ||
resolvers.push(function (value) { | ||
last(value); | ||
finish(); | ||
}); | ||
}, | ||
return: function _return(value) { | ||
return new Promise(function (resolve) { | ||
resolveAbortion = resolve; | ||
abortionResult = { value: value, done: true }; | ||
runTicks(); | ||
}); | ||
} | ||
}; | ||
}); | ||
function finish() { | ||
outputClosed = true; | ||
mergeResult = { value: value, done: true }; | ||
resolve(mergePromise); | ||
close(); | ||
} | ||
}); | ||
}), _iterator); | ||
return iterator; | ||
} | ||
module.exports = exports["default"]; |
{ | ||
"name": "mergeiterator", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "merges async iterators", | ||
"keywords": [ | ||
"merge", | ||
"iterable", | ||
"async", | ||
"iterator", | ||
"AsyncIterator" | ||
], | ||
"repository": "https://github.com/vadzim/mergeiterator", | ||
"author": "developer@vadzim.info", | ||
"contributors": [], | ||
"main": "distr/mergeiterator.js", | ||
"scripts": { | ||
"build": "babel source --out-dir distr", | ||
"prepare": "npm run build" | ||
"prettier": "prettier --write $(cat .prettier) 'source/**/*.js' 'example/**/*.js' '*.js'", | ||
"prepare": "npm run build", | ||
"test": "jest", | ||
"go": "npm run prettier && npm run build && npm run test" | ||
}, | ||
"repository": "https://github.com/vadzim/mergeiterator", | ||
"author": "v@vadzim.info", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/vadzim/mergeiterator/issues" | ||
}, | ||
"devDependencies": { | ||
@@ -18,4 +32,6 @@ "babel-cli": "^6.26.0", | ||
"babel-preset-flow": "^6.23.0", | ||
"babel-preset-stage-0": "^6.24.1" | ||
"babel-preset-stage-0": "^6.24.1", | ||
"jest": "^20.0.4", | ||
"prettier": "^1.5.3" | ||
} | ||
} |
# mergeIterator | ||
merges async iterators | ||
Merges async iterators. | ||
### Using ### | ||
This utility is for merging together async iterators. | ||
Pass it a collection of iterables and it'll return an iterator, which will contain all values from those iterables. Those iterables and the collection of them can be arrays, calls to generators, or any other kind of iterable, synchronous or async, finite or infinite. | ||
```js | ||
import merge from "mergeiterator" | ||
async function DoIt() { | ||
for await (const v of merge([ | ||
[1,2,3], | ||
(function *() { let i = 6; while (true) yield (i++) })(), | ||
(async function *() { yield await Promise.resolve(4); yield Promise.resolve(5) })(), | ||
])) { | ||
console.log(v) | ||
} | ||
} | ||
// 1 6 2 7 4 3 8 5 9 10 11 ... | ||
``` | ||
`mergeIterator` function guarantees, that if some value is yielded by some of iterables that `mergeIterator` is passed, then that value will be eventually yielded by `mergeIterator`. It also guarantees that the order of values within the same iterable is preserved. | ||
Be aware, that `mergeIterator` will wait for any promise yielded by some iterable to be resolved before yielding its value and before asking that iterable for the rest of new values. | ||
If some iterable throws an error, that error will be redirected to a caller and other iterables will be closed. | ||
### Contributing ### | ||
__Please contribute!__ | ||
All contributions are greatly appreciated no matter how small or large the contribution is. | ||
Whether it's a small grammar fix in the README, a huge bug fix, or just an issue report, you will be recognized as a 'Contributor' to this project. | ||
Please, feel free to [open an issue](https://github.com/vadzim/streamiterator/issues) or email me to developer@vadzim.info if you have any question. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
114427
7
170
0
38
7