{"id":15598803,"url":"https://github.com/lukechilds/base64-async","last_synced_at":"2025-06-29T12:34:34.261Z","repository":{"id":66309083,"uuid":"91689851","full_name":"lukechilds/base64-async","owner":"lukechilds","description":"Non-blocking chunked Base64 encoding","archived":false,"fork":false,"pushed_at":"2019-10-10T23:38:03.000Z","size":67,"stargazers_count":98,"open_issues_count":5,"forks_count":5,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-01T23:18:29.234Z","etag":null,"topics":["async","async-jobs","asynchronous","base64","chunk","chunk-size","decode","encode","non-blocking"],"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/lukechilds.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-18T12:17:41.000Z","updated_at":"2024-06-18T21:13:52.783Z","dependencies_parsed_at":"2023-03-07T13:30:28.726Z","dependency_job_id":null,"html_url":"https://github.com/lukechilds/base64-async","commit_stats":{"total_commits":103,"total_committers":3,"mean_commits":"34.333333333333336","dds":0.09708737864077666,"last_synced_commit":"6a23e3874c79c9a1589564e57d298a703e8986dc"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukechilds%2Fbase64-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukechilds%2Fbase64-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukechilds%2Fbase64-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukechilds%2Fbase64-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukechilds","download_url":"https://codeload.github.com/lukechilds/base64-async/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230408171,"owners_count":18220974,"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":["async","async-jobs","asynchronous","base64","chunk","chunk-size","decode","encode","non-blocking"],"created_at":"2024-10-03T01:41:21.888Z","updated_at":"2024-12-19T09:08:02.515Z","avatar_url":"https://github.com/lukechilds.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# base64-async\n\n\u003e Non-blocking chunked Base64 encoding\n\n[![Build Status](https://travis-ci.org/lukechilds/base64-async.svg?branch=master)](https://travis-ci.org/lukechilds/base64-async)\n[![Coverage Status](https://coveralls.io/repos/github/lukechilds/base64-async/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/base64-async?branch=master)\n[![npm](https://img.shields.io/npm/v/base64-async.svg)](https://www.npmjs.com/package/base64-async)\n\nProcess large Base64 documents without blocking the event loop.\n\nConfigurable chunk size option to optimise for your use case.\n\n\u003e **Note:**\n\u003e\n\u003e Base64 in Node.js is already crazy fast. Breaking the work up into chunks and adding async logic adds [overhead](#performance). If you aren't dealing with large files it will probably be more efficient to just block the event loop for the small amount of time it takes Node.js to process Base64 synchronously.\n\n## Install\n\n```shell\nnpm install --save base64-async\n```\n\n## Usage\n\n```js\nconst b64 = require('base64-async');\nconst fs = require('fs');\nconst buffer = fs.readFileSync('somehugefile.jpg');\n\nb64.encode(buffer).then(b64String =\u003e console.log(b64String));\n// aGkgbXVt...\n\nb64.decode(b64String).then(buffer =\u003e console.log(buffer));\n// \u003cBuffer 68 69 20 6d 75 6d ... \u003e\n\n// or, for the cool kids\nconst b64String = await b64.encode(buffer);\nconst buffer = await b64.decode(b64String);\n\n// which is equivalent to this\nconst b64String = await b64(buffer);\nconst buffer = await b64(b64String);\n// If no method is specified, buffers are encoded, strings are decoded\n```\n\n## Example\n\n```\n$ npm run example\n\nRegistering 4 asynchronous jobs...\nEncoding 100 MB with default Node.js Buffer API...\nBase64 encode complete\nHi, I'm an asynchronous job, and I'm late by 231ms\nHi, I'm an asynchronous job, and I'm late by 238ms\nHi, I'm an asynchronous job, and I'm late by 239ms\nHi, I'm an asynchronous job, and I'm late by 245ms\n\nRegistering 4 asynchronous jobs...\nEncoding 100 MB with base64-async in chunks of 250 kB...\nHi, I'm an asynchronous job, and I'm on time\nHi, I'm an asynchronous job, and I'm on time\nHi, I'm an asynchronous job, and I'm on time\nHi, I'm an asynchronous job, and I'm on time\nBase64 encode complete\n```\n\n([example source code](/examples))\n\nNotice how none of the async jobs can start until the Buffer API has finished encoding and stops blocking the event loop? With `base64-async` the async jobs can execute in-between each chunk of data.\n\n## Performance\n\n```\n$ npm run bench\n\nBenchmark completed with a chunk size of 250 kB\n┌────────┬──────────────┬──────────────┬──────────────┬──────────────┐\n│ Bytes  │ Encode Sync  │ Decode Sync  │ Encode Async │ Decode Async │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 10 kB  │ 0.097225ms   │ 0.383031ms   │ 1.276201ms   │ 0.537687ms   │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 100 kB │ 0.198161ms   │ 0.271577ms   │ 0.99799ms    │ 0.356765ms   │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 1 MB   │ 1.924415ms   │ 2.038406ms   │ 2.679117ms   │ 2.544993ms   │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 10 MB  │ 15.749204ms  │ 16.280246ms  │ 33.666111ms  │ 29.918725ms  │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 100 MB │ 165.189455ms │ 195.298199ms │ 246.359068ms │ 280.792751ms │\n└────────┴──────────────┴──────────────┴──────────────┴──────────────┘\n```\n\nAs you can see, the total processing time is longer with `base64-async` (as we spend some time paused waiting for the event loop). However, if you have an idea of the size of the data you'll be working with, you can play around with the chunk size to get better performance.\n\nThe included benchmarking tool accepts arguments to help you test this:\n\n```\n$ npm run bench -- --chunkSize=1000000 --bytesToBenchmark=50000000,100000000\n\nBenchmark completed with a chunk size of 1 MB\n┌────────┬──────────────┬──────────────┬──────────────┬──────────────┐\n│ Bytes  │ Encode Sync  │ Decode Sync  │ Encode Async │ Decode Async │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 50 MB  │ 79.675533ms  │ 87.251079ms  │ 92.400367ms  │ 137.468082ms │\n├────────┼──────────────┼──────────────┼──────────────┼──────────────┤\n│ 100 MB │ 203.423705ms │ 173.567974ms │ 186.181857ms │ 264.123311ms │\n└────────┴──────────────┴──────────────┴──────────────┴──────────────┘\n```\n\n## API\n\n### b64(input, [options])\n\nReturns a Promise that resolves to the Base64 encoded/decoded input.\n\n#### input\n\nType: `string`, `buffer`\n\nA Base64 string to decode, or a Buffer to encode.\n\n#### options\n\nType: `object`\n\n##### options.chunkSize\n\nType: `number`\u003cbr\u003e\nDefault: `250000`\n\nSize of the chunk of data to work on before deferring execution to the next iteration of the event loop.\n\nIf encoding, the number is interpreted as number of bytes. If decoding, the number is interpreted as number of characters.\n\n### b64.encode(input, [options])\n\nReturns a Promise that resolves to a Base64 encoded string.\n\n#### input\n\nType: `buffer`\n\nA Buffer to encode.\n\n### b64.decode(input, [options])\n\nReturns a Promise that resolves to a decoded Buffer.\n\n#### input\n\nType: `string`\n\nA Base64 string to decode.\n\n## License\n\nMIT © Luke Childs\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukechilds%2Fbase64-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukechilds%2Fbase64-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukechilds%2Fbase64-async/lists"}