index.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. 'use strict';
  2. const from = require('from2');
  3. const pIsPromise = require('p-is-promise');
  4. module.exports = x => {
  5. if (Array.isArray(x)) {
  6. x = x.slice();
  7. }
  8. let promise;
  9. let iterator;
  10. prepare(x);
  11. function prepare(value) {
  12. x = value;
  13. promise = pIsPromise(x) ? x : null;
  14. // we don't iterate on strings and buffers since slicing them is ~7x faster
  15. const shouldIterate = !promise && x[Symbol.iterator] && typeof x !== 'string' && !Buffer.isBuffer(x);
  16. iterator = shouldIterate ? x[Symbol.iterator]() : null;
  17. }
  18. return from(function reader(size, cb) {
  19. if (promise) {
  20. promise.then(prepare).then(() => reader.call(this, size, cb), cb);
  21. return;
  22. }
  23. if (iterator) {
  24. const obj = iterator.next();
  25. setImmediate(cb, null, obj.done ? null : obj.value);
  26. return;
  27. }
  28. if (x.length === 0) {
  29. setImmediate(cb, null, null);
  30. return;
  31. }
  32. const chunk = x.slice(0, size);
  33. x = x.slice(size);
  34. setImmediate(cb, null, chunk);
  35. });
  36. };
  37. module.exports.obj = x => {
  38. if (Array.isArray(x)) {
  39. x = x.slice();
  40. }
  41. let promise;
  42. let iterator;
  43. prepare(x);
  44. function prepare(value) {
  45. x = value;
  46. promise = pIsPromise(x) ? x : null;
  47. iterator = !promise && x[Symbol.iterator] ? x[Symbol.iterator]() : null;
  48. }
  49. return from.obj(function reader(size, cb) {
  50. if (promise) {
  51. promise.then(prepare).then(() => reader.call(this, size, cb), cb);
  52. return;
  53. }
  54. if (iterator) {
  55. const obj = iterator.next();
  56. setImmediate(cb, null, obj.done ? null : obj.value);
  57. return;
  58. }
  59. this.push(x);
  60. setImmediate(cb, null, null);
  61. });
  62. };