Helps you write libraries that accept both promises and callbacks.
Installations
npm install promise-breaker
Score
99.6
Supply Chain
99.5
Quality
76
Maintenance
100
Vulnerability
100
License
Developer
jwalton
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
Yes
Node Version
14.20.0
NPM Version
8.17.0
Statistics
85 Stars
158 Commits
2 Forks
4 Watching
4 Branches
5 Contributors
Updated on 14 Dec 2023
Languages
JavaScript (97.87%)
TypeScript (2.13%)
Total Downloads
Cumulative downloads
Total Downloads
116,523,066
Last day
3.8%
159,548
Compared to previous day
Last week
5%
874,667
Compared to previous week
Last month
8.2%
3,589,560
Compared to previous month
Last year
14.2%
37,472,598
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
What is it?
promise-breaker
makes it easy to write functions that will accept an optional callback, or return
a Promise if a callback is not provided. You can use callbacks or Promises in your implementation,
and callers can call with either a callback or expect a Promise. It's a library that makes it easy
to write libraries for others.
Installation
npm install --save promise-breaker
Requirements
This library assumes that Promise
is a defined global variable. If this is not the case
on your platform, you can use a polyfill:
npm install --save es6-promise
Then somewhere in your node.js application:
if(!global.Promise) {
global.Promise = require('es6-promise').Promise;
}
Or in your client-side app:
if(!window.Promise) {
window.Promise = require('es6-promise').Promise;
}
If you don't want to set the global, you can pass an optional Promise implementation to
promise-breaker
:
var MyPromise = require('es6-promise').Promise;
promiseBreaker = require('promise-breaker').withPromise(MyPromise);
Summary
With the growing popularity of Promises these days, if you're a library author, it's nice to be able to provide your clients with a library that will take an optional callback, and if the callback isn't provided, return a Promise. If you've ever tried to do this, you know that there's a lot of finicky boilerplate involved in every function you write. Providing callback support is also pretty important if you prefer to write your library using Promises internally.
'promise-breaker' makes this really easy. If you prefer writing in callback style:
1export function myFunc(done=null) {
2 return pb.addPromise(done, done => // Add this wrapper around your async function
3 doThing((err, thing) => {
4 if(err) {return done(err);}
5 doOtherThing(thing, (err, otherThing) => {
6 if(err) {return done(err);}
7 done(null, otherThing);
8 });
9 });
10 );
11}
or if you prefer Promise style:
1export function myFunc(done=null) {
2 return pb.addCallback(done, // Add this wrapper around your returned Promise.
3 doThing()
4 .then(result => doOtherThing(result))
5 );
6}
If you're using arrow functions or using commonjs exports, it's even easier to use promise-breaker to create functions that generate a Promise or accept a callback:
1// Both of these will take an optional `done`, and if not provided return a Promise. 2exports.myPromiseFunc = pb.break({args: 0}, () => { 3 return Promise.resolve("Hello World"); 4}); 5 6exports.myCbFunc = pb.make({args: 1}, done => { 7 done(null, "Hello World"); 8});
The names make()
and break()
here come from the idea that you are making a callback into a promise, or breaking
a promise down into a callback. Note that make()
and break()
rely on the .length
of the function you pass
in. In ES6, default parameters do not count towards the length of the function, so you need to explicitly tell
promise-breaker how many parameters are expected in the args
parameter. If you're not using default arguments, you
can omit the options parameter altogether, but this is a bad habit, as promise-breaker unfortunately has no way to
detect if you get it wrong.
The other thing you often want to do when writing a library is call into a function without knowing whether it returns a promise or expects a callback. Again, promise-breaker makes this easy:
1export function doStuff(fn) { 2 // This works just like `fn.call` except it will add a `done` if `fn.length` is bigger than the parameter count. 3 // So here, this will either call `fn("hello world")` and get back a Promise or `fn("hello world", done)` and 4 // convert the callback into a Promise for you. 5 pb.call(fn, null, "hello world") 6 .catch(err => console.log(err)); 7}
Or, in callback style:
1export function doStuff(fn) {
2 pb.callWithCb(fn, null, "hello world", err => {
3 if(err) return console.log(err);
4 });
5}
API
pb.make([options,] fn)
options.args
- In ES6, default parameters do not count towards a functions.length
. If yourfn
uses default parameters, you must specify the total parameter count inargs
. E.g.:const myFn = pb.make({args: 2}, (x, y=null) => ...);
If you do not specifyargs
, then promise-breaker will usefn.length
instead.
make()
takes a function which accepts a callback(err, result)
as its last parameter, and
returns a new function which accepts an optional callback as its last parameter. If a callback is
provided, this new function will behave exactly like the original function. If the callback
is not provided, then the new function will return a Promise.
Since Promises only allow a single value to be returned, if fn
passes more than two arguments to callback(...)
,
then (as of v3.0.0) any arguments after the error will be transformed into an array and returned via the Promise as a
single combined argument. This does not affect the case where the transformed function is called with a callback.
For example:
var myFunc = pb.make(function(callback) {
// We're returning multiple values via callback
callback(null, "a", "b");
})
// Callback style
myFunc(function(err, a, b) {...});
// Promise style
myFunc()
.then(function(results) {
// Promises only let us return a single value, so we return an array.
var a = results[0];
var b = results[1];
...
})
.catch(function(err) {...});
pb.break([options,] fn)
options.args
- In ES6, default parameters do not count towards a functions.length
. If yourfn
uses default parameters, you must specify the total parameter count inargs
. E.g.:const myFn = pb.break({args: 3}, (x, y=null, done=null) => ...);
If you do not specifyargs
, then promise-breaker will usefn.length
instead.
break(fn)
is the opposite of make(fn)
. fn
here is a function which returns a Promise.
break(fn)
will generate a new function with an extra parameter, an optional
callback(err, result)
. If no callback is provided, the generated function will behave exactly
like the original function. If a callback is provided, then the generated function will return
null
, and will pass any results that would have been returned via the Promise via the callback
instead.
addPromise(done, fn)
Used to add Promise support to a callback-based function.
Calls fn(cb)
. If done
is provided, it is passed directly as cb
and addPromise
returns undefined. If done
is not provided, addPromise
will generate an appropriate callback and return a Promise. If fn
is called with
more than two arguments (with multiple results, in other words) then the Promise will resolve to an array of results.
Use it like this:
1export function addAsync(x, y, done=null) {
2 return pb.addPromise(done, done => done(null, x + y));
3}
addCallback(done, promise)
Used to add callback support to a promise-based function.
If done
is not provided, returns the promise
passed in. If done
is
provided, this will wait for promise
to resolve or reject and then call
done(err, result)
appropriately. Note that promise
can also be a
function that takes no arguments and returns a Promise.
Use it like this:
1export function addAsync(x, y, done=null) {
2 return pb.addCallback(done, Promise.resolve(x + y));
3}
pb.apply(fn, thisArg, args[, cb])
Much like Function.prototype.apply()
,
this calls a function, but this lets you call into a function when you don't know whether the
function is expecting a callback or is going to return a Promise. fn
is the function you wish
to call. Under the hood, if fn.length
is equal to args.length
, this will call fn
with the parameters provided, and then return the Promise (or wrap a returned value in a Promise).
If fn.length
is args.length + 1
, then a callback will be added.
If cb
is provided, apply
will call into cb
with a result, otherwise apply
will itself
return a Promise.
pb.call(fn, thisArg[, arg1[, arg2[, ...]]))
This is the Function.prototype.call()
equivalent of apply()
. Note that this always returns a Promise. If you need a callback, use callWithCb()
instead.
Note that this is handy shortcut for promisifying a callback-based API:
1pb.call(done => fs.readFile(filename, {encoding: 'utf8'}, done)) 2.then(fileContents => ...);
pb.callWithCb(fn, argumentCount, thisArg[, arg1[, arg2[, ...[, cb]]]])
Similar to pb.call()
, but instead of returning a Promise this will call the provided callback.
pb.withPromise(promiseImpl)
Returns a new {make, break, addPromise, addCallback, apply, call, callWithCb}
object which uses the specified
promiseImpl constructor to create new Promises.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 0/16 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/github-ci.yaml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/github-ci.yaml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/jwalton/node-promise-breaker/github-ci.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/github-ci.yaml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/jwalton/node-promise-breaker/github-ci.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/github-ci.yaml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/jwalton/node-promise-breaker/github-ci.yaml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/github-ci.yaml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/jwalton/node-promise-breaker/github-ci.yaml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/github-ci.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/jwalton/node-promise-breaker/github-ci.yaml/master?enable=pin
- Warn: npmCommand not pinned by hash: .github/workflows/github-ci.yaml:17
- Warn: npmCommand not pinned by hash: .github/workflows/github-ci.yaml:34
- Info: 0 out of 4 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 1 third-party GitHubAction dependencies pinned
- Info: 0 out of 2 npmCommand dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 16 are checked with a SAST tool
Score
3.4
/10
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to promise-breaker
amqp-connection-manager
Auto-reconnect and round robin support for amqplib.
opossum
A fail-fast circuit breaker for promises and callbacks
cockatiel
A resilience and transient-fault-handling library that allows developers to express policies such as Backoff, Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Inspired by .NET Polly.
grapheme-breaker
An implementation of the Unicode grapheme cluster breaking algorithm (UAX #29)