Promisify a callback-style function

Overview

pify

Promisify a callback-style function

Install

$ npm install pify

Usage

const fs = require('fs');
const pify = require('pify');

(async () => {
	// Promisify a single function.
	const data = await pify(fs.readFile)('package.json', 'utf8');
	console.log(JSON.parse(data).name);
	//=> 'pify'

	// Promisify all methods in a module.
	const data2 = await pify(fs).readFile('package.json', 'utf8');
	console.log(JSON.parse(data2).name);
	//=> 'pify'
})();

API

pify(input, options?)

Returns a Promise wrapped version of the supplied function or module.

input

Type: Function | object

Callback-style function or module whose methods you want to promisify.

options

Type: object

multiArgs

Type: boolean
Default: false

By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like request that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument. This also applies to rejections, where it returns an array of all the callback arguments, including the error.

const request = require('request');
const pify = require('pify');

const pRequest = pify(request, {multiArgs: true});

(async () => {
	const [httpResponse, body] = await pRequest('https://sindresorhus.com');
})();
include

Type: Array<string | RegExp>

Methods in a module to promisify. Remaining methods will be left untouched.

exclude

Type: Array<string | RegExp>
Default: [/.+(?:Sync|Stream)$/]

Methods in a module not to promisify. Methods with names ending with 'Sync' are excluded by default.

excludeMain

Type: boolean
Default: false

If the given module is a function itself, it will be promisified. Enable this option if you want to promisify only methods of the module.

const pify = require('pify');

function fn() {
	return true;
}

fn.method = (data, callback) => {
	setImmediate(() => {
		callback(null, data);
	});
};

(async () => {
	// Promisify methods but not `fn()`.
	const promiseFn = pify(fn, {excludeMain: true});

	if (promiseFn()) {
		console.log(await promiseFn.method('hi'));
	}
})();
errorFirst

Type: boolean
Default: true

Whether the callback has an error as the first argument. You'll want to set this to false if you're dealing with an API that doesn't have an error as the first argument, like fs.exists(), some browser APIs, Chrome Extension APIs, etc.

promiseModule

Type: Function

Custom promise module to use instead of the native one.

FAQ

How is this different from Node.js's util.promisify?

  • Pify existed long before util.promisify.
  • Pify is faster.
  • Pify supports wrapping a whole module/object, not just a specific method.
  • Pify has useful options like the ability to handle multiple arguments (multiArgs).
  • Pify does not have magic behavior for certain Node.js methods and instead focuses on predictability.

How can I promisify a single class method?

Class methods are not bound, so when they're not called on the class itself, they don't have any context. You can either promisify the whole class or use .bind().

const pify = require('pify');
const SomeClass = require('./some-class');

const someInstance = new SomeClass();

// ❌ `someFunction` can't access its class context.
const someFunction = pify(someClass.someFunction);

// ✅ The whole class is promisified and the `someFunction` method is called on its class.
const someClassPromisified = pify(someClass);
someClassPromisified.someFunction();

// ✅ `someFunction` is bound to its class before being promisified.
const someFunction = pify(someClass.someFunction.bind(someClass));

Related

  • p-event - Promisify an event by waiting for it to be emitted
  • p-map - Map over promises concurrently
  • More…

Get professional support for 'pify' with a Tidelift subscription
Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies.
Comments
  • Support transforming inherited methods

    Support transforming inherited methods

    This makes it possible to transform objects which are instances of a class without knowing which methods are present on the instance object and which are inherited through the prototype chain, as discussed in #14. Include/Exclude is handled the same as for non-inherited methods.

    In addition to transforming inherited methods, when the inherited option is enabled the result object is created with the prototype of the original object so that it behaves the same as the original object for instanceof checks. I think this fits with the intended use of inherited, but if you would prefer a separate option or a separate PR, let me know and I'll split it out.

    This PR also copies all properties from the original object to the target, even if excluded, to match the current behavior. It may make more sense to avoid copying values and/or excluded methods which would be inherited, both to avoid unnecessary copies and so any updates to the prototype are shared. But I left that behavior out of this PR for simplicity. Let me know if you would prefer that behavior.

    Thanks for considering, Kevin

    Fixes #14

    opened by kevinoid 35
  • add bind option

    add bind option

    By default, it binds functions to the original object.

    If opts.bind is false. It does not bind to the original object, and copies over all non-function properties.

    Closes #26.

    opened by jamestalmage 15
  • Return ES2015 Proxy object

    Return ES2015 Proxy object

    Issuehunt badges

    ECMAScript6 Proxies are currently not available on node, therefore this issue is a reminder for future versions.

    pify(obj) should return an ECMAScript6 Proxy object, forwarding almost all operations to obj, and promisifying only some functions, thus we almost surely get rid of most non-enumerable and inheritance issues.


    IssueHunt Summary

    frangio frangio has been rewarded.

    Backers (Total: $70.00)

    Submitted pull Requests


    Tips


    IssueHunt has been backed by the following sponsors. Become a sponsor

    enhancement help wanted :gift: Rewarded on Issuehunt 
    opened by schnittstabil 14
  • Add TypeScript definitions

    Add TypeScript definitions

    Closes #74

    Pros and cons compared to #85

    Pros:

    • No need for as many overloads
    • Supports as many generics as you like
    • Support for as many callback arguments as you like when multiArgs: true. Although not sure if this is in scope in the context of the errorFirst options.

    Cons:

    • pify((v: number) => {})() returns Promise<unknown> instead of erroring - at runtime this promise will simply never resolve or reject. A bit of annoying DX but isn't unsafe.

    Todo:

    • [x] Promisifying modules with includes and excludes
    • [x] Document clearly that overloaded functions are not supported and only the final overload will be chosen: https://github.com/microsoft/TypeScript/issues/32164
    • [x] Support excludeMain
    • [x] Support errorFirst

    IssueHunt Summary

    Referenced issues

    This pull request has been submitted to:


    opened by tom-sherman 12
  • Add TypeScript type definition

    Add TypeScript type definition

    Issuehunt badges

    Would be nice to have TypeScript type definitions bundled in this package. The types should be strict and should be generic so it preserves the original function type.

    The type definition should follow this styleguide, and should have full docs and type tests.

    Some examples:

    • https://github.com/sindresorhus/semver-regex/commit/039944bb5b3876913171b895488874b5c200e458
    • https://github.com/sindresorhus/global-dirs/commit/0aae4d64887f77af94c4fb7ca12aa9f93c0a8291
    • https://github.com/sindresorhus/md5-hex/commit/bbbfeff840f26973fbffc16d4863ae6d120079f3

    Note that this is not an easy task and requires you to have advanced TypeScript experience. There have been multiple attempts and a lot of wasted time on my part in the past. If you intend to work on this, please look at the previous attempts and the feedback given there.


    IssueHunt Summary

    tom-sherman tom-sherman has been rewarded.

    Backers (Total: $100.00)

    Submitted pull Requests


    Tips

    help wanted :gift: Rewarded on Issuehunt 
    opened by sindresorhus 12
  • pify for gm doesn't seems to be working

    pify for gm doesn't seems to be working

    Hi,

    I'm trying to fix AVA tests for some functionality and I need to Promisify gm(...).size() function. Unfortunately I'm not able to do that properly:

    const out = await pify(gm(image.data).size());
    console.log("gm output: " + out.width);
    ---
      gm output: undefined
    
    const out = await pify(gm(image.data).size)();
    console.log("gm output: " + out.width);
    ---
      1 failed
    
      resize-jpeg › Resize JPEG with jpegoptim
      Error: Cannot read property 'size' of undefined
        proto.(anonymous function) (node_modules/gm/lib/getters.js:47:20)
        node_modules/pify/index.js:29:7
        node_modules/pify/index.js:12:10
        ret (node_modules/pify/index.js:56:34)
        Test.<anonymous> (test/resize-jpeg.js:37:20)
        Generator.next (<anonymous>)
    
    const out = await pify(gm(image.data).size.bind(gm))();
    console.log("gm output: " + out.width);
    ---
      1 failed
    
      resize-jpeg › Resize JPEG with jpegoptim
      Error: Cannot read property 'size' of undefined
        proto.(anonymous function) (node_modules/gm/lib/getters.js:47:20)
        node_modules/pify/index.js:29:7
        node_modules/pify/index.js:12:10
        ret (node_modules/pify/index.js:56:34)
        Test.<anonymous> (test/resize-jpeg.js:37:20)
        Generator.next (<anonymous>)
    
    const out = await pify(gm(image.data)).size();
    console.log("gm output: " + out.width);
    ---
      1 failed
    
      resize-jpeg › Resize JPEG with jpegoptim
      Error: pify(...).size is not a function
        Test.<anonymous> (test/resize-jpeg.js:37:43)
        Generator.next (<anonymous>)
    

    So, my question is: if it's possible to pify gm and if so, I would like to know how?

    opened by kdybicz 12
  • Add TypeScript definition

    Add TypeScript definition

    Closes #74 and takes over #75.

    If I missed something, glad to receive better inspirations from you guys.


    IssueHunt Summary

    Referenced issues

    This pull request has been submitted to:


    IssueHunt has been backed by the following sponsors. Become a sponsor

    opened by chinesedfan 11
  • Allow promisification of a single object method:

    Allow promisification of a single object method:

    This allows opts to be a string. If so, it will promisify the named function of input and return a thunk with this bound to input.

    This is really handy for chainable structures, where binding this can get a little verbose:

    var bundler = browserify()
      .require(file)
      .transform(brfs)
      .exclued(excluded);
    
    return pify(bundler.bundle.bind(bundler))();
    

    becomes

    return pify(
      browserify()
        .require(file)
        .transform(brfs)
        .exclued(excluded),
      'bundle'
    )();
    
    opened by jamestalmage 10
  • Add TypeScript definition

    Add TypeScript definition

    Solves #74

    • works with generics(up to 6 arguments and 5 returned values)
    • works with anything except generics for any number of arguments
    • doesn't use include and exclude for typing, as we can't test RegExp while typing

    IssueHunt Summary

    Referenced issues

    This pull request has been submitted to:


    opened by stroncium 9
  • Add TypeScript definition

    Add TypeScript definition

    opened by satyarohith 9
  • Methods for keeping this

    Methods for keeping this

    I find that I quite often need to preserve this when calling functions that takes callbacks. I have used something similar to the code below, but I would like to hear what you think of the matter.

    Is there an easy way to support this use case?

    function promise (obj, fn) {
      return pify(obj[fn]).bind(obj)
    }
    
    await promise(linus, 'walk')(100, 'miles')
    console.log('Linus walked 100 miles')
    
    // vs.
    
    linus.walk(100, 'miles', () => console.log('Linus walked 100 miles'))
    
    opened by LinusU 9
Releases(v6.1.0)
  • v6.1.0(Sep 2, 2022)

  • v6.0.0(Jun 6, 2022)

  • v5.0.0(Feb 14, 2020)

    Breaking

    • Require Node.js 10 a6c20b3

    Enhancements

    • Implement using Proxy (#73) 57e9a04 This means that it should work seamlessly in more cases as the promisified function is just a transparent wrapper around the original function.

    https://github.com/sindresorhus/pify/compare/v4.0.1...v5.0.0

    Source code(tar.gz)
    Source code(zip)
  • v4.0.1(Oct 24, 2018)

    • Bring back support for promisifying prototype functions. It was accidentally left out in v4. https://github.com/sindresorhus/pify/commit/bbe89b74a46272bc2a8c9b39b2b15a690e359ddd
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Oct 24, 2018)

    Breaking:

    • Require Node.js 6. https://github.com/sindresorhus/pify/commit/523bad995294079f19b8d66e4d92aecaca1504e7

    Other:

    • Check for invalid input. https://github.com/sindresorhus/pify/commit/9ef944cf168cb589b611c48f5ef06bd5ea736a3c
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(May 28, 2017)

    • Now requires Node.js 4.
    • Made multiArgs option apply on rejections too. https://github.com/sindresorhus/pify/commit/30116d9ca0e683f3e2c184bfc53a7061d0efbba3
    • Moved promiseModule argument into an option. https://github.com/sindresorhus/pify/commit/5f7259cad178f8460480e37549c04741c99cfadc
    • Supports transforming inherited methods and bind methods to original object. https://github.com/sindresorhus/pify/commit/1701541b76e66978aaf7655e0cae4e274b138079
    • Added option to support non-error-first APIs. https://github.com/sindresorhus/pify/commit/fad7b3d2dfa4ad90e304107bd500799e07be538b
    • Excludes methods ending in Stream by default. https://github.com/sindresorhus/pify/commit/a2cec4cb0cb0fbe398123e76b1ce30e8a9943be4

    https://github.com/sindresorhus/pify/compare/v2.3.0...v3.0.0

    Source code(tar.gz)
    Source code(zip)
Owner
Sindre Sorhus
Full-Time Open-Sourcerer. Wants more empathy & kindness in open source. Focuses on Swift & JavaScript. Makes macOS apps, CLI tools, npm packages. Likes unicorns
Sindre Sorhus
Limit the execution rate of a function

valvelet This is a small utility to limit the execution rate of a function. It is useful for scenarios such as REST APIs consumption where the amount

Luigi Pinca 38 Dec 26, 2022
🚀 Tiny goodies for Continuation-Passing-Style functions, fully tested

// ) ) ___ ___ ___ __//__ // ) ) // ) ) (( ) ) // // / / // //___/ / \ \ // ((___/ / ((___

Dmitri Zaitsev 64 Nov 20, 2022
The invoker based on event model provides an elegant way to call your methods in another container via promisify functions

The invoker based on event model provides an elegant way to call your methods in another container via promisify functions. (like child-processes, iframe, web worker etc).

尹挚 7 Dec 29, 2022
A lightweight function that executes callback when we see specific DOM elements.

did-i-see A lightweight function that executes callback when we see specific DOM elements. Built with IntersectionObserver. ?? Demo: https://did-i-see

Kaan Ersoy 4 Oct 18, 2022
A quickstart AWS Lambda function code generator. Downloads a template function code file, test harness file, sample SAM deffiniation and appropriate file structure.

Welcome to function-stencil ?? A quickstart AWS Lambda function code generator. Downloads a template function code file, test harness file, sample SAM

Ben Smith 21 Jun 20, 2022
Tries to execute sync/async function, returns a specified default value if the function throws

good-try Tries to execute sync/async function, returns a specified default value if the function throws. Why Why not nice-try with it's 70+ million do

Antonio Stoilkov 14 Dec 8, 2022
Wrap a function with bun-livereload to automatically reload any imports inside the function the next time it is called

bun-livereload Wrap a function with bun-livereload to automatically reload any imports inside the function the next time it is called. import liveRelo

Jarred Sumner 19 Dec 19, 2022
Base62-token.js - Generate & Verify GitHub-style & npm-style Base62 Tokens

base62-token.js Generate & Verify GitHub-style & npm-style Secure Base62 Tokens Works in Vanilla JS (Browsers), Node.js, and Webpack. Online Demo See

Root 4 Jun 11, 2022
Clock and task scheduler for node.js applications, providing extensive control of time and callback scheduling in prod and test code

#zeit A node.js clock and scheduler, intended to take place of the global V8 object for manipulation of time and task scheduling which would be handle

David Denton 12 Dec 21, 2021
Callback-free control flow for Node using ES6 generators.

suspend Generator-based control-flow for Node enabling asynchronous code without callbacks, transpiling, or selling your soul. Suspend is designed to

Jeremy Martin 550 Jul 9, 2022
Clock and task scheduler for node.js applications, providing extensive control of time and callback scheduling in prod and test code

#zeit A node.js clock and scheduler, intended to take place of the global V8 object for manipulation of time and task scheduling which would be handle

David Denton 12 Dec 21, 2021
A enhanced web storage with env support, expire time control, change callback and LRU storage clear strategy.

enhanced-web-storage A enhanced web storage with env support, expire time control, change callback and LRU storage clear strategy. How to Start import

Ziwen Mei 15 Sep 10, 2021
Cypress commands are asynchronous. It's a common pattern to use a then callback to get the value of a cypress command

cypress-thenify Rationale Cypress commands are asynchronous. It's a common pattern to use a then callback to get the value of a cypress command. Howev

Mikhail Bolotov 15 Oct 2, 2022
Simple patch that adds a 'progress' callback to jquery Ajax calls

Jquery Ajax Progresss A simple patch to jQuery that will call a 'progress' callback, using the XHR.onProgress event Usage Simply include the script on

Chad Engler 118 Sep 8, 2022
Detect F12 open console, protect web static resources, support redirect, rewrite, callback strategies.

console-ban Detect F12 open browser console. protect web site static resources, support redirect, rewrite, custom callback strategies. Language: Engli

Yingci 623 Dec 26, 2022
JavaScript micro-library: pass in an element and a callback and this will trigger when you click anywhere other than the element

Add a click listener to fire a callback for everywhere on the window except your chosen element. Installation run npm install @lukeboyle/when-clicked-

Boyleing Point 5 May 13, 2021
Plug-and-play, faster-than-native promise/callback event emitter

kNow Blazing-fast callback/promise-based events with a tiny footprint What is this? With kNow (pronounced "now"—the k's silent), JavaScript event mana

Elijah Bodden 25 Sep 11, 2022
Create a HTML table from JSON that can be sorted, selected, and post-processed using a simple callback.

Tidy Table Create a HTML table from JSON that can be sorted, selected, and post-processed using a simple callback. Features Extensible HTML/CSS interf

Marc S. Brooks 50 Aug 16, 2022
Create Bootstrap 5 Modal Box using JavaScript with custom title, description, button labels and custom YES button callback

Dynamic BS5 Modal Box Create Bootstrap 5 Modal Box using JavaScript with custom title, description, button labels and custom YES button callback Insta

null 5 Oct 23, 2022
A JavaScript library to watch the DOM changes in a single callback

watchmydom A Javascript library to watch the DOM changes in a single callback Demo Click here to see the detailed demo. Download Minified script file

Muhammed Saifudeen (saif) 2 Oct 30, 2020