{"id":18895955,"url":"https://github.com/jwalton/node-promise-breaker","last_synced_at":"2025-04-05T10:09:06.096Z","repository":{"id":33694361,"uuid":"37347299","full_name":"jwalton/node-promise-breaker","owner":"jwalton","description":"Helps you write libraries that accept both promises and callbacks.","archived":false,"fork":false,"pushed_at":"2023-04-03T10:57:30.000Z","size":302,"stargazers_count":85,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T09:10:34.048Z","etag":null,"topics":["async","callback","javascript","javascript-library","promise"],"latest_commit_sha":null,"homepage":null,"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/jwalton.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2015-06-12T22:19:05.000Z","updated_at":"2023-12-14T08:23:10.000Z","dependencies_parsed_at":"2024-06-18T15:20:28.066Z","dependency_job_id":null,"html_url":"https://github.com/jwalton/node-promise-breaker","commit_stats":{"total_commits":134,"total_committers":11,"mean_commits":"12.181818181818182","dds":"0.35820895522388063","last_synced_commit":"d37a4174aef27ff68c1e824d46152cc2a652073b"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwalton%2Fnode-promise-breaker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwalton%2Fnode-promise-breaker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwalton%2Fnode-promise-breaker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwalton%2Fnode-promise-breaker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwalton","download_url":"https://codeload.github.com/jwalton/node-promise-breaker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247318745,"owners_count":20919484,"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","callback","javascript","javascript-library","promise"],"created_at":"2024-11-08T08:31:34.014Z","updated_at":"2025-04-05T10:09:06.081Z","avatar_url":"https://github.com/jwalton.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Build Status](https://github.com/jwalton/node-promise-breaker/workflows/GitHub%20CI/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/jwalton/node-promise-breaker/badge.svg)](https://coveralls.io/r/jwalton/node-promise-breaker)\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\n## What is it?\n\n`promise-breaker` makes it easy to write functions that will accept an optional callback, or return\na Promise if a callback is not provided.  You can use callbacks or Promises in your implementation,\nand callers can call with either a callback or expect a Promise.  It's a library that makes it easy\nto write libraries for others.\n\n## Installation\n\n    npm install --save promise-breaker\n\n## Requirements\n\nThis library assumes that `Promise` is a defined global variable.  If this is not the case\non your platform, you can use a polyfill:\n\n    npm install --save es6-promise\n\nThen somewhere in your node.js application:\n\n    if(!global.Promise) {\n        global.Promise = require('es6-promise').Promise;\n    }\n\nOr in your client-side app:\n\n    if(!window.Promise) {\n        window.Promise = require('es6-promise').Promise;\n    }\n\nIf you don't want to set the global, you can pass an optional Promise implementation to\n`promise-breaker`:\n\n    var MyPromise = require('es6-promise').Promise;\n    promiseBreaker = require('promise-breaker').withPromise(MyPromise);\n\n## Summary\n\nWith the growing popularity of Promises these days, if you're a library author, it's nice to\nbe able to provide your clients with a library that will take an optional callback, and if the\ncallback isn't provided, return a Promise.  If you've ever tried to do this, you know that there's\na lot of finicky boilerplate involved in every function you write.  Providing callback support is\nalso pretty important if you prefer to write your library using Promises internally.\n\n'promise-breaker' makes this really easy.  If you prefer writing in callback style:\n\n```js\nexport function myFunc(done=null) {\n    return pb.addPromise(done, done =\u003e // Add this wrapper around your async function\n        doThing((err, thing) =\u003e {\n            if(err) {return done(err);}\n            doOtherThing(thing, (err, otherThing) =\u003e {\n                if(err) {return done(err);}\n                done(null, otherThing);\n            });\n        });\n    );\n}\n```\n\nor if you prefer Promise style:\n\n```js\nexport function myFunc(done=null) {\n    return pb.addCallback(done, // Add this wrapper around your returned Promise.\n        doThing()\n        .then(result =\u003e doOtherThing(result))\n    );\n}\n```\n\nIf you're using arrow functions or using commonjs exports, it's even easier to use\npromise-breaker to create functions that generate a Promise or accept a callback:\n\n```js\n// Both of these will take an optional `done`, and if not provided return a Promise.\nexports.myPromiseFunc = pb.break({args: 0}, () =\u003e {\n    return Promise.resolve(\"Hello World\");\n});\n\nexports.myCbFunc = pb.make({args: 1}, done =\u003e {\n    done(null, \"Hello World\");\n});\n```\n\nThe names `make()` and `break()` here come from the idea that you are making a callback into a promise, or breaking\na promise down into a callback.  Note that `make()` and `break()` rely on the `.length` of the function you pass\nin.  In ES6, default parameters do not count towards the length of the function, so you need to explicitly tell\npromise-breaker how many parameters are expected in the `args` parameter.  If you're not using default arguments, you\ncan omit the options parameter altogether, but this is a bad habit, as promise-breaker unfortunately has no way to\ndetect if you get it wrong.\n\nThe other thing you often want to do when writing a library is call into a function without knowing whether\nit returns a promise or expects a callback.  Again, promise-breaker makes this easy:\n\n```js\nexport function doStuff(fn) {\n    // This works just like `fn.call` except it will add a `done` if `fn.length` is bigger than the parameter count.\n    // So here, this will either call `fn(\"hello world\")` and get back a Promise or `fn(\"hello world\", done)` and\n    // convert the callback into a Promise for you.\n    pb.call(fn, null, \"hello world\")\n    .catch(err =\u003e console.log(err));\n}\n```\n\nOr, in callback style:\n\n```js\nexport function doStuff(fn) {\n    pb.callWithCb(fn, null, \"hello world\", err =\u003e {\n        if(err) return console.log(err);\n    });\n}\n```\n\n## API\n\n### pb.make([options,] fn)\n\n* `options.args` - In ES6, default parameters do not count towards a functions `.length`.  If your `fn`\n  uses default parameters, you must specify the total parameter count in `args`.  E.g.:\n  `const myFn = pb.make({args: 2}, (x, y=null) =\u003e ...);`  If you do not specify `args`, then promise-breaker\n  will use `fn.length` instead.\n\n`make()` takes a function which accepts a `callback(err, result)` as its last parameter, and\nreturns a new function which accepts an optional callback as its last parameter.  If a callback is\nprovided, this new function will behave exactly like the original function.  If the callback\nis not provided, then the new function will return a Promise.\n\nSince Promises only allow a single value to be returned, if `fn` passes more than two arguments to `callback(...)`,\nthen (as of v3.0.0) any arguments after the error will be transformed into an array and returned via the Promise as a\nsingle combined argument.  This does not affect the case where the transformed function is called with a callback.\n\nFor example:\n\n    var myFunc = pb.make(function(callback) {\n        // We're returning multiple values via callback\n        callback(null, \"a\", \"b\");\n    })\n\n    // Callback style\n    myFunc(function(err, a, b) {...});\n\n    // Promise style\n    myFunc()\n    .then(function(results) {\n        // Promises only let us return a single value, so we return an array.\n        var a = results[0];\n        var b = results[1];\n        ...\n    })\n    .catch(function(err) {...});\n\n\n### pb.break([options,] fn)\n\n* `options.args` - In ES6, default parameters do not count towards a functions `.length`.  If your `fn`\n  uses default parameters, you must specify the total parameter count in `args`.  E.g.:\n  `const myFn = pb.break({args: 3}, (x, y=null, done=null) =\u003e ...);`  If you do not specify `args`,\n  then promise-breaker will use `fn.length` instead.\n\n`break(fn)` is the opposite of `make(fn)`.  `fn` here is a function which returns a Promise.\n`break(fn)` will generate a new function with an extra parameter, an optional\n`callback(err, result)`.  If no callback is provided, the generated function will behave exactly\nlike the original function.  If a callback is provided, then the generated function will return\n`null`, and will pass any results that would have been returned via the Promise via the callback\ninstead.\n\n### addPromise(done, fn)\n\nUsed to add Promise support to a callback-based function.\n\nCalls `fn(cb)`.  If `done` is provided, it is passed directly as `cb` and `addPromise` returns undefined.  If `done`\nis not provided, `addPromise` will generate an appropriate callback and return a Promise.  If `fn` is called with\nmore than two arguments (with multiple results, in other words) then the Promise will resolve to an array of results.\n\n\nUse it like this:\n\n```js\nexport function addAsync(x, y, done=null) {\n    return pb.addPromise(done, done =\u003e done(null, x + y));\n}\n```\n\n### addCallback(done, promise)\n\nUsed to add callback support to a promise-based function.\n\nIf `done` is not provided, returns the `promise` passed in.  If `done` is\nprovided, this will wait for `promise` to resolve or reject and then call\n`done(err, result)` appropriately.  Note that `promise` can also be a\nfunction that takes no arguments and returns a Promise.\n\nUse it like this:\n\n```js\nexport function addAsync(x, y, done=null) {\n    return pb.addCallback(done, Promise.resolve(x + y));\n}\n```\n\n### pb.apply(fn, thisArg, args[, cb])\n\nMuch like [`Function.prototype.apply()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call),\nthis calls a function, but this lets you call into a function when you don't know whether the\nfunction is expecting a callback or is going to return a Promise.  `fn` is the function you wish\nto call.  Under the hood, if `fn.length` is equal to `args.length`, this will call `fn`\nwith the parameters provided, and then return the Promise (or wrap a returned value in a Promise).\nIf `fn.length` is `args.length + 1`, then a callback will be added.\n\nIf `cb` is provided, `apply` will call into `cb` with a result, otherwise `apply` will itself\nreturn a Promise.\n\n### pb.call(fn, thisArg[, arg1[, arg2[, ...]]))\n\nThis is the [`Function.prototype.call()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)\nequivalent of `apply()`.  Note that this always returns a Promise.  If you need a callback, use `callWithCb()`\ninstead.\n\nNote that this is handy shortcut for promisifying a callback-based API:\n\n```js\npb.call(done =\u003e fs.readFile(filename, {encoding: 'utf8'}, done))\n.then(fileContents =\u003e ...);\n```\n\n### pb.callWithCb(fn, argumentCount, thisArg[, arg1[, arg2[, ...[, cb]]]])\n\nSimilar to `pb.call()`, but instead of returning a Promise this will call the provided callback.\n\n### pb.withPromise(promiseImpl)\n\nReturns a new `{make, break, addPromise, addCallback, apply, call, callWithCb}` object which uses the specified\npromiseImpl constructor to create new Promises.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwalton%2Fnode-promise-breaker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwalton%2Fnode-promise-breaker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwalton%2Fnode-promise-breaker/lists"}