Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Require Node.js 10
  • Loading branch information
sindresorhus committed Feb 14, 2020
1 parent 57e9a04 commit a6c20b3
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 143 deletions.
3 changes: 1 addition & 2 deletions .gitattributes
@@ -1,2 +1 @@
* text=auto
*.js text eol=lf
* text=auto eol=lf
1 change: 0 additions & 1 deletion .travis.yml
Expand Up @@ -2,4 +2,3 @@ language: node_js
node_js:
- '12'
- '10'
- '8'
41 changes: 21 additions & 20 deletions index.js
@@ -1,11 +1,11 @@
'use strict';

const processFn = (fn, options, proxy, unwrapped) => function (...args) {
const processFn = (fn, options, proxy, unwrapped) => function (...arguments_) {
const P = options.promiseModule;

return new P((resolve, reject) => {
if (options.multiArgs) {
args.push((...result) => {
arguments_.push((...result) => {
if (options.errorFirst) {
if (result[0]) {
reject(result);
Expand All @@ -18,34 +18,35 @@ const processFn = (fn, options, proxy, unwrapped) => function (...args) {
}
});
} else if (options.errorFirst) {
args.push((error, result) => {
arguments_.push((error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
} else {
args.push(resolve);
arguments_.push(resolve);
}

const self = this === proxy ? unwrapped : this;
Reflect.apply(fn, self, args);
Reflect.apply(fn, self, arguments_);
});
};

const filterCache = new WeakMap();

module.exports = (input, options) => {
options = Object.assign({
exclude: [/.+(Sync|Stream)$/],
options = {
exclude: [/.+(?:Sync|Stream)$/],
errorFirst: true,
promiseModule: Promise
}, options);
promiseModule: Promise,
...options
};

const objType = typeof input;
if (!(input !== null && (objType === 'object' || objType === 'function'))) {
throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``);
const objectType = typeof input;
if (!(input !== null && (objectType === 'object' || objectType === 'function'))) {
throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objectType}\``);
}

const filter = (target, key) => {
Expand Down Expand Up @@ -85,26 +86,26 @@ module.exports = (input, options) => {
},

get(target, key) {
const prop = target[key];
const property = target[key];

// eslint-disable-next-line no-use-extend-native/no-use-extend-native
if (!filter(target, key) || prop === Function.prototype[key]) {
return prop;
if (!filter(target, key) || property === Function.prototype[key]) {
return property;
}

const cached = cache.get(prop);
const cached = cache.get(property);

if (cached) {
return cached;
}

if (typeof prop === 'function') {
const pified = processFn(prop, options, proxy, target);
cache.set(prop, pified);
if (typeof property === 'function') {
const pified = processFn(property, options, proxy, target);
cache.set(property, pified);
return pified;
}

return prop;
return property;
}
});

Expand Down
2 changes: 1 addition & 1 deletion license
@@ -1,6 +1,6 @@
MIT License

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
27 changes: 14 additions & 13 deletions optimization-test.js
Expand Up @@ -26,19 +26,20 @@ function assertOptimized(fn, name) {
}
}

const sut = pify({
unicorn: cb => {
cb(null, 'unicorn');
const fn = pify({
unicorn: callback => {
callback(null, 'unicorn');
}
});

sut.unicorn().then(() => {
v8.optimizeFunctionOnNextCall(sut.unicorn);

return sut.unicorn().then(() => {
assertOptimized(sut.unicorn, 'unicorn');
});
}).catch(error => {
console.error(error.stack);
process.exit(1); // eslint-disable-line unicorn/no-process-exit
});
(async () => {
try {
await fn.unicorn();
v8.optimizeFunctionOnNextCall(fn.unicorn);
await fn.unicorn();
assertOptimized(fn.unicorn, 'unicorn');
} catch (error) {
console.error(error);
process.exit(1); // eslint-disable-line unicorn/no-process-exit
}
})();
14 changes: 6 additions & 8 deletions package.json
Expand Up @@ -4,13 +4,14 @@
"description": "Promisify a callback-style function",
"license": "MIT",
"repository": "sindresorhus/pify",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=6"
"node": ">=10"
},
"scripts": {
"test": "xo && ava",
Expand All @@ -20,14 +21,12 @@
"index.js"
],
"keywords": [
"promisify",
"callback",
"promise",
"promises",
"promisify",
"all",
"denodify",
"denodeify",
"callback",
"cb",
"node",
"then",
"thenify",
Expand All @@ -36,7 +35,6 @@
"wrap",
"wrapper",
"bind",
"to",
"async",
"await",
"es2015",
Expand All @@ -46,6 +44,6 @@
"ava": "^2.4.0",
"pinkie-promise": "^2.0.0",
"v8-natives": "^1.1.0",
"xo": "^0.23.0"
"xo": "^0.26.1"
}
}
22 changes: 8 additions & 14 deletions readme.md
Expand Up @@ -2,34 +2,31 @@

> Promisify a callback-style function

## Install

```
$ npm install pify
```


## Usage

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

(async () => {
// Promisify a single function
// 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
// 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?)
Expand All @@ -48,7 +45,7 @@ Type: `object`

##### multiArgs

Type: `boolean`<br>
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.
Expand All @@ -72,14 +69,14 @@ Methods in a module to promisify. Remaining methods will be left untouched.

##### exclude

Type: `Array<string | RegExp>`<br>
Default: `[/.+(Sync|Stream)$/]`
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`<br>
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.
Expand All @@ -98,7 +95,7 @@ fn.method = (data, callback) => {
};

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

if (promiseFn()) {
Expand All @@ -109,7 +106,7 @@ fn.method = (data, callback) => {

##### errorFirst

Type: `boolean`<br>
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.
Expand All @@ -120,7 +117,6 @@ Type: `Function`

Custom promise module to use instead of the native one.


## FAQ

#### How is this different from Node.js's [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)?
Expand All @@ -131,14 +127,12 @@ Custom promise module to use instead of the native one.
- Pify has useful options like the ability to handle multiple arguments (`multiArgs`).
- Pify does not have [magic behavior](https://nodejs.org/api/util.html#util_custom_promisified_functions) for certain Node.js methods and instead focuses on predictability.


## Related

- [p-event](https://github.com/sindresorhus/p-event) - Promisify an event by waiting for it to be emitted
- [p-map](https://github.com/sindresorhus/p-map) - Map over promises concurrently
- [More…](https://github.com/sindresorhus/promise-fun)


---

<div align="center">
Expand Down

0 comments on commit a6c20b3

Please sign in to comment.