{"id":18398360,"url":"https://github.com/jiayihu/sinergia","last_synced_at":"2025-10-16T04:26:13.693Z","repository":{"id":57361699,"uuid":"87641958","full_name":"jiayihu/sinergia","owner":"jiayihu","description":"⚒️ Cooperative expensive tasks at 60fps via ES6 generators","archived":false,"fork":false,"pushed_at":"2017-05-21T10:50:19.000Z","size":117,"stargazers_count":161,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-01T22:50:17.426Z","etag":null,"topics":["60fps","expensive-tasks","generators","requestanimationframe"],"latest_commit_sha":null,"homepage":"https://jiayihu.github.io/sinergia/","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/jiayihu.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":"2017-04-08T15:01:14.000Z","updated_at":"2025-01-18T13:09:57.000Z","dependencies_parsed_at":"2022-09-26T16:41:03.493Z","dependency_job_id":null,"html_url":"https://github.com/jiayihu/sinergia","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiayihu%2Fsinergia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiayihu%2Fsinergia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiayihu%2Fsinergia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiayihu%2Fsinergia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jiayihu","download_url":"https://codeload.github.com/jiayihu/sinergia/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595370,"owners_count":20963939,"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","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":["60fps","expensive-tasks","generators","requestanimationframe"],"created_at":"2024-11-06T02:21:41.562Z","updated_at":"2025-10-16T04:26:13.584Z","avatar_url":"https://github.com/jiayihu.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sinergia\n\n[![npm](https://img.shields.io/npm/v/sinergia.svg)](https://www.npmjs.com/package/sinergia) [![travis](https://travis-ci.org/jiayihu/sinergia.svg?branch=master)](https://travis-ci.org/jiayihu/sinergia)\n\n**sinergia** is a tiny (1KB gzipped) library to run [cooperative](https://en.wikipedia.org/wiki/Cooperative_multitasking) expensive tasks  without blocking the UI during the computations and keeping 60fps frame rate.\n\n## Demo\n\nA live example is available at [https://jiayihu.github.io/sinergia/](https://jiayihu.github.io/sinergia/), with an animated box which should remain smooth at 60fps.\n\nThere are 2 examples:\n\n1. [Long running loop](https://jiayihu.github.io/sinergia/#loop): Running an expensive function (with a 2mln iterations loop) with each item of an iterable\n\n2. [Long merge sort](https://jiayihu.github.io/sinergia/#merge-sort): Running a common merge sort with an array of 100k items\n\nIt's possible to play with the demo locally cloning the repo and running:\n\n```bash\ncd demo # Go to demo folder\nnpm install # Or `yarn install`\nnpm start\n```\n\n## Installation\n\n```\nnpm install sinergia --save\n```\n\n## Usage\n\n\u003e The following examples use [co](https://github.com/tj/co) to consume the generator functions.  \n\nIn this example `work` runs a long loop for every item, but every 100000 iterations it interrupts and gives the control to `sinergia`, which will resume the execution of `work` when more suitable.  \n\nExecution tasks are by definition [cooperative](https://en.wikipedia.org/wiki/Cooperative_multitasking) because they decide when to `yield` the control of the execution.\n\nBy using `yield` inside your `work` you can decide the priority of the execution. *Yielding* often will run the task smoothly chunk by chunk but it will complete in more time. On the other hand *yielding* fewer times it will complete the task sooner but it will block more the main thread. *Yielding* zero times is equal to running the task *synchronously*.\n\n```javascript\nimport co from 'co';\nimport { sinergia } from 'sinergia';\n\nfunction* work() {\n  const iterable = 'Absent gods.'.split('');\n  let result = '';\n\n  for (let item of iterable) {\n    let x = 0;\n\n    while (x \u003c 2000000) {\n      x = x + 1;\n\n      // Tell sinergia when the task can be interrupted and resumed later\n      if (x % 100000 === 0) yield result;\n    }\n\n    result += item; // Simple result of task\n    console.log(`Result of iteration:`, result);\n  }\n\n  yield result; // Yield latest result\n}\n\nconst execute = co(function* () {\n  return yield* sinergia(work);\n});\nexecute.then((result) =\u003e {\n  // If the work wasn't interrupted\n  if (result) console.log(`Result: ${result.value}`);\n});\n```\n\n### Abort execution\n\nSince `sinergia` is just a generator, you can use the returned object to abort the execution using [.return()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) method of generators.\n\nThe method will return `{ value: any }` with the value of the result computed on the latest item before aborting.\n\n```javascript\nimport co from 'co';\nimport { sinergia } from 'sinergia';\n\nfunction* work() {\n  const iterable = 'Absent gods.'.split('');\n  let result = '';\n\n  for (let item of iterable) {\n    let x = 0;\n\n    while (x \u003c 2000000) {\n      x = x + 1;\n\n      // Tell sinergia when the task can be interrupted and resumed later\n      if (x % 100000 === 0) yield result;\n    }\n\n    result += item; // Simple result of task\n    console.log(`Result of iteration:`, result);\n  }\n\n  yield result; // Yield latest result\n}\n\nlet iterator;\n\nconst execute = co(function* () {\n  iterator = sinergia(work);\n  return yield* iterator;\n});\nexecute.then((result) =\u003e {\n  // If the work wasn't interrupted\n  if (result) console.log(`Result: ${result.value}`);\n});\n\nwindow.setTimeout(() =\u003e {\n  const result = iterator.return();\n  console.log('Interrupted result', result.value);\n}, 5000);\n```\n\n## API\n\n#### sinergia(work: GeneratorFunction): Generator\n\nIt runs asynchronously the `work` function in not blocking way.\nReturns the [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) object.\n\n## Browser support\n\n**sinergia** requires polyfills for:\n\n1. *Promise* like [es6-promise](https://github.com/stefanpenner/es6-promise) or [core-js Promise](https://github.com/zloirock/core-js#ecmascript-6-promise). If you use [babel-polyfill](https://babeljs.io/docs/usage/polyfill/) it's already included.\n\n2. *requestAnimationFrame/cancelAnimationFrame*. See this [gist](https://gist.github.com/paulirish/1579671) as example.\n\n## Credits\n\nIspiration comes largely from [@LucaColonnello](https://github.com/LucaColonnello) and [@cef62](https://github.com/cef62).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiayihu%2Fsinergia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiayihu%2Fsinergia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiayihu%2Fsinergia/lists"}