{"id":19658141,"url":"https://github.com/cdaringe/promise_fns","last_synced_at":"2026-05-15T06:09:57.895Z","repository":{"id":49988901,"uuid":"350802124","full_name":"cdaringe/promise_fns","owner":"cdaringe","description":"Promise utility functions for Deno","archived":false,"fork":false,"pushed_at":"2023-12-15T08:23:43.000Z","size":72,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-18T06:08:48.655Z","etag":null,"topics":["bluebird","deno","promise","promise-fns","promise-fun","promise-funs","utilities"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdaringe.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":".github/contributing.md","funding":null,"license":null,"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":"2021-03-23T17:36:35.000Z","updated_at":"2021-04-24T20:39:11.000Z","dependencies_parsed_at":"2024-11-11T15:38:47.911Z","dependency_job_id":null,"html_url":"https://github.com/cdaringe/promise_fns","commit_stats":{"total_commits":44,"total_committers":3,"mean_commits":"14.666666666666666","dds":0.4545454545454546,"last_synced_commit":"16835909b0c436786fd5a916967337fdc4107b1c"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdaringe%2Fpromise_fns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdaringe%2Fpromise_fns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdaringe%2Fpromise_fns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdaringe%2Fpromise_fns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdaringe","download_url":"https://codeload.github.com/cdaringe/promise_fns/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240965809,"owners_count":19885968,"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":["bluebird","deno","promise","promise-fns","promise-fun","promise-funs","utilities"],"created_at":"2024-11-11T15:36:13.763Z","updated_at":"2026-05-15T06:09:57.845Z","avatar_url":"https://github.com/cdaringe.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# promise_fns\n\nPromise utility functions for Deno.\n\n[![main](https://github.com/cdaringe/promise_fns/actions/workflows/main.yml/badge.svg)](https://github.com/cdaringe/promise_fns/actions/workflows/main.yml)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\nInspired by the sindresorhus\n[promise-fun](https://github.com/sindresorhus/promise-fun) collection. Parity\nwith the node `promise-fun` library is not guaranteed.\n\n**Features**:\n\n- functions are independently importable\n- type safe, type reflecting APIs\n- concurrency control for most collection iterating functions\n- debuggable. simplified source, named functions (so your stack trace is\n  legible!)\n\n## Table Of Contents\n\n\u003c!-- toc --\u003e\n\n- [Usage](#usage)\n- [Functions](#functions)\n  - [all](#all)\n  - [allLazy](#alllazy)\n  - [catchIf](#catchif)\n  - [delay](#delay)\n  - [delayReject](#delayreject)\n  - [event](#event)\n  - [if](#if)\n  - [log](#log)\n  - [logCatch](#logcatch)\n  - [map](#map)\n  - [promisify](#promisify)\n  - [promisifyMulti](#promisifymulti)\n  - [props](#props)\n  - [queue](#queue)\n  - [tap](#tap)\n  - [tapCatch](#tapcatch)\n- [Demo support functions](#demo-support-functions)\n- [contributing](#contributing)\n\n\u003c!-- tocstop --\u003e\n\n## Usage\n\nYou can import any individual function as follows:\n\n```ts {skipRun: true}\nimport fn from \"https://deno.land/x/promise_fns/src/FUNCTION_NAME.ts\";\nfn(...)\n```\n\nAll functions are listed in the [functions table](#functions).\n\nA full example:\n\n```ts {skipRun: true}\nimport delay from \"https://deno.land/x/promise_fns/src/delay.ts\";\nconst delayedTwo = await delay(100, 2);\nconsole.log(1 + delayedTwo); // 3\n```\n\n## Functions\n\n### all\n\nresolve a collection of promises. it's just\n[Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)\n\n[src](./src/all.ts) [test](./test/all.test.ts)\n\n```ts {group: demo, file: {name: \"readme.ts\", autoRemove: true}}\n// eager\nimport all from \"./src/all.ts\";\nconsole.log(await all([countFiles(\".\"), testIsFile(\"readme.md\")]));\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n[ 13, true ]\n```\n\n### allLazy\n\nresolve a lazy collection of promises. that is, execute and resolve a collection\nof thunks that return promises.\n\n[src](./src/allLazy.ts) [test](./test/allLazy.test.ts)\n\n```ts {group: demo}\nimport allLazy from \"./src/allLazy.ts\";\nconsole.log(\n  await allLazy([() =\u003e countFiles(\"test\"), () =\u003e testIsFile(\"test\")])\n);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n[ 19, false ]\n```\n\n### catchIf\n\nconditional promise catch handler\n\n[src](./src/catchIf.ts) [test](./test/catchIf.test.ts)\n\n```ts {group: demo }\nimport catchIf from \"./src/catchIf.ts\";\nconst useZeroOnMissing = catchIf(\n  (err) =\u003e !!err?.message.match(/No such file/),\n  () =\u003e 0\n);\nconst filesInBogusDir = await countFiles(\"/bogus/directory\")\n  .then(console.log)\n  .catch(useZeroOnMissing);\nconsole.log({ filesInBogusDir });\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n{ filesInBogusDir: 0 }\n```\n\n### delay\n\ncreate a promise that sleeps for some milliseconds then resolves\n\n[src](./src/delay.ts) [test](./test/delay.test.ts)\n\n```ts {group: demo}\nimport delay from \"./src/delay.ts\";\nconst delay5 = delay(5).then(() =\u003e console.log(5));\nconst delay1 = delay(1).then(() =\u003e console.log(1));\nconst delay3 = delay(3).then(() =\u003e console.log(3));\nawait all([delay5, delay1, delay3]);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n1\n3\n5\n```\n\n### delayReject\n\ncreate a promise that sleeps for some milliseconds then rejects\n\n[src](./src/delayReject.ts) [test](./test/delayReject.test.ts)\n\n```ts {group: demo}\nimport delayReject from \"./src/delayReject.ts\";\nconst delayReject5 = delayReject(5, new Error(`${5}`)).catch(console.error);\nconst delayReject1 = delayReject(1, new Error(`${1}`)).catch(console.error);\nconst delayReject3 = delayReject(3, new Error(`${3}`)).catch(console.error);\nawait all([delayReject5, delayReject1, delayReject3]);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nError: 1\n    at file:///home/cdaringe/src/promise-fns/readme.ts:20:37\nError: 3\n    at file:///home/cdaringe/src/promise-fns/readme.ts:21:37\nError: 5\n    at file:///home/cdaringe/src/promise-fns/readme.ts:19:37\n```\n\n### event\n\nawait an event completion in a promise\n\n[src](./src/event.ts) [test](./test/event.test.ts)\n\n```ts {group: demo}\nimport event from \"./src/event.ts\";\nimport { EventEmitter } from \"./test/fixture/3p.ts\";\nclass TestEmitter extends EventEmitter\u003c{ foo: [string] }\u003e {}\nconst emitter = new TestEmitter();\nconst resolvesOnEvent = event(emitter, \"on\", \"foo\");\nemitter.emit(\"foo\", \"bar\");\nconsole.log({ emittedValue: await resolvesOnEvent });\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n{ emittedValue: [ \"bar\" ] }\n```\n\n### if\n\nconditional promise chains\n\n[src](./src/if.ts) [test](./test/if.test.ts)\n\n```ts {group: demo}\nimport pIf from \"./src/if.ts\";\nconsole.log({\n  youReceived: await Promise.resolve(\"big money!\").then(\n    pIf(\n      Math.random() \u003e 1 / 1e9,\n      (prize) =\u003e `congrats, ${prize}`,\n      () =\u003e \"sorry, zero bucks :(\"\n    )\n  ),\n});\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n{ youReceived: \"congrats, big money!\" }\n```\n\n### log\n\nlog the resolved value of a promise\n\n[src](./src/log.ts) [test](./test/log.test.ts)\n\n```ts {group: demo}\nimport createPromiseLogger from \"./src/log.ts\";\nconst pLog = createPromiseLogger\u003cnumber\u003e(console.info);\nawait Promise.resolve(1)\n  .then(pLog)\n  .then((v) =\u003e v + 1)\n  .then(pLog);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n1\n2\n```\n\n### logCatch\n\nLog the rejected value of a promise\n\n[src](./src/logCatch.ts) [test](./test/logCatch.test.ts)\n\n```ts {group: demo}\nimport createLogCatch from \"./src/logCatch.ts\";\nawait Promise.reject(new Error(\"something terrible has happened\"))\n  .catch(createLogCatch())\n  .catch(() =\u003e null);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nError: something terrible has happened\n    at file:///home/cdaringe/src/promise-fns/readme.ts:43:22\n```\n\n### map\n\nmaps a collection into a new collection asynchronously\n\n[src](./src/map.ts) [test](./test/map.test.ts)\n\n```ts {group: demo}\nimport map from \"./src/map.ts\";\nconst mapped = await map([\"readme.md\", \"tacos.now\"], testIsFile);\nconsole.log(mapped);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n[ true, false ]\n```\n\n### promisify\n\nconverts a node-style callback function into a promisified function, returning\nthe result after `err`, per `(err, result) =\u003e void`\n\n[src](./src/promisify.ts) [test](./test/promisify.test.ts)\n\n```ts {group: demo}\nimport promisify from \"./src/promisify.ts\";\ntype OldSkoolFn = (cb: (err: Error | null, result: string) =\u003e void) =\u003e void;\nconst cbStyleFn: OldSkoolFn = (cb) =\u003e cb(null, \"yippy. skippy.\");\nconst coolFn = promisify(cbStyleFn);\nconsole.log(await coolFn());\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nyippy. skippy.\n```\n\n### promisifyMulti\n\nconverts a node-style callback function into a promisified function, returning\nall results after `err`, per `(err, ...results) =\u003e void`\n\n[src](./src/promisifyMulti.ts) [test](./test/promisifyMulti.test.ts)\n\n```ts {group: demo}\nimport promisifyMulti from \"./src/promisifyMulti.ts\";\ntype OldSkoolFnMulti = (\n  cb: (err: Error | null, ...results: string[]) =\u003e void\n) =\u003e void;\nconst cbStyleMultiFn: OldSkoolFnMulti = (cb) =\u003e cb(null, \"uno\", \"dos\", \"tres\");\nconst coolMultiFn = promisifyMulti(cbStyleMultiFn);\nconsole.log(await coolMultiFn());\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\n[ \"uno\", \"dos\", \"tres\" ]\n```\n\n### props\n\nmaps a { key:promise } mapped collection to a `{ key:resolved-promise }` mapped\ncollection\n\n[src](./src/props.ts) [test](./test/props.test.ts)\n\n```ts {group: demo}\nimport props from \"./src/props.ts\";\nconsole.log(\n  await props({\n    pbAndJ: delay(1).then(() =\u003e \"incredible\"),\n    subway: delay(3).then(() =\u003e \"legally not bread in ireland\"),\n    cubano: delay(0).then(() =\u003e \"oooooh baby!\"),\n  }).then((result) =\u003e `PB and J is ${result.pbAndJ}`)\n);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nPB and J is incredible\n```\n\n### queue\n\ncreates a queue that allows users to add work. queue resolves when no work is\noutstanding\n\n[src](./src/queue.ts) [test](./test/queue.test.ts)\n\n```ts {group: demo}\nimport createQueue from \"./src/queue.ts\";\nconst plannedWork = [5, 0, 3];\nconst { add, queue, subscribe } = createQueue\u003cnumber\u003e({ concurrency: 1 });\nsubscribe((v) =\u003e console.log(`completed work: ${v}`));\nfor (const ms of plannedWork) {\n  console.log(`adding work ${ms} to queue`);\n  const work = () =\u003e delay(ms).then(() =\u003e ms);\n  add(work);\n}\nconst result = await queue;\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nadding work 5 to queue\nadding work 0 to queue\nadding work 3 to queue\ncompleted work: 5\ncompleted work: 0\ncompleted work: 3\n```\n\n### tap\n\nTap into a resolving promise chain without affecting the resolved value\n\n[src](./src/tap.ts) [test](./test/tap.test.ts)\n\n```ts {group: demo}\nimport tap from \"./src/tap.ts\";\nawait countFiles(\".\").then(tap((n) =\u003e console.log(`found ${n} files`)));\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\nfound 13 files\n```\n\n### tapCatch\n\ntap into a rejecting promise chain without affecting the rejected value\n\n[src](./src/tapCatch.ts) [test](./test/tapCatch.test.ts)\n\n```ts {group: demo}\nimport tapCatch from \"./src/tapCatch.ts\";\nawait countFiles(\"/bogus\")\n  .catch(tapCatch(() =\u003e console.error(`count files failed, but its all good`)))\n  .catch(() =\u003e 0);\n```\n\n```txt {skipRun: true, isExecutionOutput: true}\ncount files failed, but its all good\n```\n\n**More functions are on their way!**\n\n## Demo support functions\n\nThe demo functions used in the above demos are defined as follows:\n\n```ts {group: demo}\nasync function countFiles(dirname: string) {\n  let i = 0;\n  for await (const _ of Deno.readDir(dirname)) ++i;\n  return i;\n}\nfunction testIsFile(filename: string): Promise\u003cboolean\u003e {\n  return Deno.stat(filename)\n    .then(({ isFile }) =\u003e isFile)\n    .catch(() =\u003e false);\n}\n```\n\n## contributing\n\nWanting to add more _great stuff?_. See\n[.github/contributing.md](.github/contributing.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdaringe%2Fpromise_fns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdaringe%2Fpromise_fns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdaringe%2Fpromise_fns/lists"}