{"id":17497519,"url":"https://github.com/miguelcastillo/coseq","last_synced_at":"2025-10-25T20:06:57.636Z","repository":{"id":57209614,"uuid":"77491412","full_name":"MiguelCastillo/coseq","owner":"MiguelCastillo","description":"high order functions for JavaScript async/sync iterators ","archived":false,"fork":false,"pushed_at":"2017-11-12T16:55:53.000Z","size":36,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-01T19:03:26.111Z","etag":null,"topics":["async-iterators","asynchronous","chain","coroutines","iterator","javascript","promise","sequence","yield"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MiguelCastillo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-28T00:49:52.000Z","updated_at":"2023-04-17T18:27:21.000Z","dependencies_parsed_at":"2022-09-01T07:51:16.733Z","dependency_job_id":null,"html_url":"https://github.com/MiguelCastillo/coseq","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/MiguelCastillo/coseq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiguelCastillo%2Fcoseq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiguelCastillo%2Fcoseq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiguelCastillo%2Fcoseq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiguelCastillo%2Fcoseq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MiguelCastillo","download_url":"https://codeload.github.com/MiguelCastillo/coseq/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiguelCastillo%2Fcoseq/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267678448,"owners_count":24126333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async-iterators","asynchronous","chain","coroutines","iterator","javascript","promise","sequence","yield"],"created_at":"2024-10-19T15:53:34.851Z","updated_at":"2025-10-25T20:06:52.595Z","avatar_url":"https://github.com/MiguelCastillo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# coseq\n\n[![Build Status](https://travis-ci.org/MiguelCastillo/coseq.svg?branch=master)](https://travis-ci.org/MiguelCastillo/coseq)[![Greenkeeper badge](https://badges.greenkeeper.io/MiguelCastillo/coseq.svg)](https://greenkeeper.io/)\n\nCompose chains of functions to manipulate data via *synchronous and asynchronous iterators*. Data iteration is lazy, which means that items are not read/evaluated until the data is needed. This allows for a really nice integration with infinite and/or really large data sets where eager evaluation and itermediate data storage is prohibitively expensive or impossible.\n\n\u003e [async iterators](https://github.com/tc39/proposal-async-iteration) are a thing in JavaScript.\n\nThe first use case is around generators, which can create *asynchronous and synchrnous iterators*. You can craft generators to yield anything you want (more than once), in which case they are referred to as coroutines. Combining the coroutine nature of generators and the ability to iterate over the data they yield is why the name `coseq` came about. Not very creative - I know.\n\n\u003e subroutines return one value. coroutines can yield multiple values before running to completion.\n\nYou can take a look at this [codepen](http://codepen.io/MiguelCastillo/pen/KNLMZq?editors=0010) if you want to play with `coseq`.\n\n\n# features\n\n- Lazy data evaluation\n  - infinite data sequence\n  - large data sets\n- No intermediate arrays\n- Asynchronous and synchronous iterators\n  - Compatibility with `for await (var x of iterator)` and `for (var x of iterator)`\n\n\n# usage\n\n## install\n\n```\n$ npm install coseq --save\n```\n\n## api\n\n### coseq\n\nMethod that wraps an iterator to create chains of high order functions to process your data.\n\nThe contract with `coseq` is the [iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), which is why anything that can create an interator can be used with `coseq`. This includes `array`, `Set`, `Map`... etc.\n\nBelow is an example of filtering even numbers and multiplying the values by 2.\n\n``` javascript\nimport coseq from 'coseq'\n\nconst set = new Set([1, 2, 3, 4]);\n\nconst sequence = coseq(set.values())\n  .filter(value =\u003e value % 2)\n  .map(value =\u003e value * 2);\n\nfor (var value of sequence) {\n  console.log(value);\n}\n```\n\nThe potential of coseq can be more easily experienced with infinite or really large data sets. *Generators are a good example of this.*\n\n\n``` javascript\nfunction* getItemsSync() {\n  for (var i = 1; i \u003c= 5000000; i++) {\n    yield i;\n  }\n\n  return \"YES!!\";\n}\n\nconst sequence = coseq(getItemsSync())\n  .skip(500)\n  .filter(value =\u003e value % 2)\n  .map(value =\u003e value * 2);\n\nfor (var value of sequence) {\n  console.log(value);\n}\n```\n\nBelow is a contrived example with *async generators*.\n\n``` javascript\nasync function* getItemsAsync() {\n  for (var i = 1; i \u003c= 5000000; i++) {\n    yield await i;\n  }\n\n  return \"YES!!\";\n}\n\nconst sequence = coseq(getItemsAsync())\n  .filter(value =\u003e value % 2)\n  .map(value =\u003e value * 2);\n\nasync function runSequence(sequence) {\n  for await (var value of sequence) {\n    console.log(value);\n  }\n}\n\nrunSequence(sequence);\n```\n\nYou can also await values in the sequence with the helper method `awaitValue`.\n\n``` javascript\nasync function* getItemsAsync() {\n  for (var i = 1; i \u003c= 5000000; i++) {\n    yield await Promise.resolve(i); // \u003c== This yields promises that can be awaited with awaitValue\n  }\n\n  return \"YES!!\";\n}\n\nconst sequence = coseq(getItemsAsync())\n  .awaitValue() // \u003c== This will await the promise yielded by the iterator\n  .filter(value =\u003e value % 2)\n  .map(value =\u003e value * 2);\n  \nasync function runSequence(sequence) {\n  for await (var value of sequence) {\n    console.log(value);\n  }\n}\n\nrunSequence(sequence);\n```\n\n\n### filter\n\nMethod to skip items in a sequence when the provided predicate returns falsy values.\n\n\u003e alias `where`\n\n``` javascript\ncoseq(getItemsAsync()).filter(value =\u003e value % 2);\n```\n\n### map\n\nMethod to transform the current value in the sequence.\n\n\u003e alias `select`\n\n``` javascript\ncoseq(getItemsAsync()).map(value =\u003e value * 2);\n```\n\n### forEach\n\nMethod to iterate through the items in a sequence. You can use this instead of the `for of` and `for await of` constructs.\n\n\u003e `forEach` runs asynchronously and returns a promise, which is particularly useful for accessing to the value returned by generator functions.\n\nIn the example below, all values are printed out in the `forEach`. And when the generator is all done generating values, the last `then` method in the chain will print `YES!!`;\n\n``` javascript\nasync function* getItemsAsync() {\n  for (var i = 1; i \u003c= 5000000; i++) {\n    yield await i;\n  }\n\n  return \"YES!!\";\n}\n\ncoseq(getItemsAsync())\n  .filter(value =\u003e value % 2)\n  .map(value =\u003e value * 2)\n  .forEach(value =\u003e console.log(result.value))\n  .then(result =\u003e console.log(result.value));\n```\n\n### take\n\nMethod to read a specific number of items from a sequence. This is a one time operation so once the specified number of items are read, no further values will be processed.\n\nThe example below will pull the first 3 items\n\n``` javascript\ncoseq(getItemsAsync()).take(3);\n```\n\n### takeUntil\n\nMethod to read items from a sequence until the predicate function returns true. This is a one time operation so once the condition is true, the sequence will no longer return values.\n\nThe example below will pull items until the value is equal to 2, including 2.\n\n``` javascript\ncoseq(getItemsAsync()).takeUntil(value =\u003e value === 2);\n```\n\n### takeWhile\n\nMethod to read items from a sequence while the predicate function returns true. This is a one time operation so once the condition is no longer satisfied, the sequence will no longer return values.\n\nThe example below will pull items while the value is smaller or equal to 2\n\n``` javascript\ncoseq(getItemsAsync()).takeWhile(value =\u003e value \u003c= 2);\n```\n\n### skip\n\nMethod to skip (discard) a specific number of items in a sequence. This is a one time operation so once the specified number of items are read, no more items will be skipped.\n\nThe example below skips the first 3 items.\n\n``` javascript\ncoseq(getItemsAsync()).skip(3);\n```\n\n### skipUntil\n\nMethod to skip (discard) items until the provided predicate function returns true. This is a one time operation so once the condition is true, `skipUntil` will no longer skip items.\n\nThe example below skips until the value is 3.\n\n``` javascript\ncoseq(getItemsAsync()).skipUntil(value =\u003e value === 3);\n```\n\n### skipWhile\n\nMethod to skip (discard) items while the provided predicate function return true. This is a one time operation so once the condition is true, `skipWhile` will no longer skip items.\n\nThe example below skips while the value is 1.\n\n``` javascript\ncoseq(getItemsAsync()).skipWhile(value =\u003e value === 1);\n```\n\n### awaitValue (async sequence only)\n\nMethod to await the current value. The primary use case for this is when a sequence yields a promise which needs to be awaited.\n\n``` javascript\ncoseq(getItemsAsync())\n  .awaitValue()\n  .skipUntil(value =\u003e value === 2);\n```\n\n### delay (async sequence only)\n\nMethod to add a delay before continuing to process the current item in the sequence. The delay is sepecified in *milliseconds*.\n\n``` javascript\ncoseq(getItemsAsync())\n  .skipUntil(value =\u003e value === 2)\n  .delay(3000);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiguelcastillo%2Fcoseq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiguelcastillo%2Fcoseq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiguelcastillo%2Fcoseq/lists"}