Skip to content

Commit

Permalink
Merge pull request #5 from vinniegarcia/multi-return
Browse files Browse the repository at this point in the history
Support multiple return values via array, fixes #4
  • Loading branch information
vinniegarcia committed Jul 9, 2015
2 parents 5894899 + 6978edb commit e12fb92
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: node_js
node_js:
- "0.12"
- "0.11"
- "0.10"
- "iojs-v1.4.2"
- "iojs-v2.3.3"
install: npm i
script: npm test
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![travis build information](https://api.travis-ci.org/vinniegarcia/proposal.svg)](https://travis-ci.org/vinniegarcia/proposal)
[![Coverage Status](https://coveralls.io/repos/vinniegarcia/proposal/badge.svg)](https://coveralls.io/r/vinniegarcia/proposal)

Callback to Promise converter. A `Proposal` is a bridge function between node-style asynchronous functions with callbacks in the form of `(err, data) => void` (which from here on out I'll refer to as `nodebacks`) and ECMAScript 6 `Promises`.
Callback to Promise converter. A `Proposal` is a bridge function between node-style asynchronous functions with callbacks in the form of `(err, data) => void` or `(err, [data]) => void` (which from here on out I'll refer to as `nodebacks`) and ECMAScript 6 `Promises`.

## Installation
Required: [nodejs](http://nodejs.org/) (tested against v0.10 and 0.12), or [io.js](https://iojs.org/) (tested against v1.4.2), [npm](https://www.npmjs.com/).
Expand Down Expand Up @@ -96,6 +96,11 @@ var fs = require('fs'),
var buffy = Proposal(crypto.randomBytes, 512);
console.log(buffy instanceof Promise); // => true, is not a value
```
3. _I have another question that's not listed here._
3. _My nodeback has several data return values, like [`child_process.exec`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback), which, on success, returns an `stdout` and an `stderr` Buffer. Is this supported?_

Yes, in this case `resolve` will return an `Array` with the data return values. While ugly-ish,
it does work well in practice, as multiple arguments are [not allowed](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) in `onFulfilled`.

4. _I have another question that's not listed here._

Raise an issue and I'll get to it as soon as I can. Thanks for reading this far!
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "proposal",
"version": "1.1.1",
"version": "1.2.0",
"description": "Takes a node-style callbacking function and converts it into a Promise automagically",
"main": "dist/index.js",
"scripts": {
"lint": "eslint src/**/*.es6",
"compile": "babel --experimental -d dist/ src/",
"compile": "babel --stage 0 -d dist/ src/",
"copydata": "mkdir -p dist/test/fixtures && cp -R src/test/fixtures/* dist/test/fixtures/",
"cc": "npm run compile && npm run copydata",
"prepublish": "npm run cc",
"mocha": "npm run cc && ./node_modules/mocha/bin/_mocha dist/test/*.js",
"mocha": "npm run cc && ./node_modules/mocha/bin/_mocha dist/test/*.js --timeout 10000",
"istanbul": "npm run cc && istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly dist/test/*.js",
"coverage": "npm run cc && istanbul cover ./node_modules/mocha/bin/_mocha --report html dist/test/*.js",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage",
Expand All @@ -32,12 +32,13 @@
"homepage": "https://github.com/vinniegarcia/proposal",
"devDependencies": {
"coveralls": "^2.11.2",
"istanbul": "^0.3.7",
"mocha": "^2.1.0",
"httpreq": "^0.4.12",
"istanbul": "^0.3.17",
"mocha": "^2.2.5",
"mocha-lcov-reporter": "0.0.2",
"node-emoji": "^0.1.0"
},
"dependencies": {
"babel": "^4.6.3"
"babel": "^5.6.14"
}
}
16 changes: 16 additions & 0 deletions src/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{

"parser": "babel-eslint",
"env": {
"browser": false,
"es6": true,
"node": true
},

"rules": {
"quotes": [2, "single"],
"eol-last": [0],
"no-mixed-requires": [0],
"no-underscore-dangle": [0]
}
}
16 changes: 9 additions & 7 deletions src/index.es6
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

import 'babel/polyfill';

//convert the err,data callback to promise resolve/reject calls
const denode = (resolve, reject) => (err, data) => (err) ? reject(err) : resolve(data);
// Converts the (err, data) or (err, [data]) callback to Promise resolve/reject calls.
// Resolves with either the data or the [data] fulfillment argument, as onFulfilled
// takes exactly one argument (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then).
const denode = (resolve, reject) => (err, ...args) => (err) ? reject(err) : resolve((args.length > 1) ? args : args[0]);

//take a node-style function that sends an (err, result)
//callback and turns it into a promise
// Takes a node-style function that sends an (err, result) or (err, [result])
// callback and turns it into a Promise.
const promiseMe = (f, ...args) => new Promise((resolve, reject) => f(...args, denode(resolve, reject)));

//waits for parameters before creating the Promise
// Waits for parameters before creating the Promise.
const curryWrap = (f) => (...more) => promiseMe(f, ...more);

// if args given, return a promise for the operation.
// if not, return a new function that waits for more input.
// If args are given, returns a Promise for the operation.
// Else, returns a new function that waits for more input.
const Proposal = (nodefn, ...args) => (args.length > 0) ? promiseMe(nodefn, ...args) : curryWrap(nodefn);

export default Proposal;
18 changes: 18 additions & 0 deletions src/test/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{

"parser": "babel-eslint",
"env": {
"browser": false,
"es6": true,
"node": true,
"mocha": true
},

"rules": {
"quotes": [2, "single"],
"new-cap": false,
"eol-last": [0],
"no-mixed-requires": [0],
"no-underscore-dangle": [0]
}
}
54 changes: 54 additions & 0 deletions src/test/multi-return.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

import {ok} from 'assert';
import http from 'http';
import req from 'httpreq';
import {exec} from 'child_process';
import { h1, cool, fw } from './fixtures/emoji';
import Proposal from '../index';

describe(h1('multiple return values test'), () => {
const handler = (req, res) => {
res.writeHead(200);
res.end(fw('TEST RESULT\n'));
},
serv = http.createServer(handler);
serv.on('listening', () => {
console.log(fw('server listening'));
});

before((done) => {
serv.listen(8912);
done();
});

after((done) => {
serv.close(done);
});

it(cool('returns one value, the response of a http get call'), (done) => {
const getIt = Proposal(req.get);

getIt('http://localhost:8912/').then((response) => {
ok(!Array.isArray(response));
done();
})
.catch(done);
});

it(cool('returns multiple values, the stdout and stderr from an executed child process'),
async function (done) {
this.timeout(10000);

const futureExec = Proposal(exec);
try {
const [stout, sterr] = await futureExec('curl -# http://127.0.0.1:8912/', {});
ok(typeof stout === 'string' && typeof sterr === 'string');
done();
} catch (err) {
done(err);
}
}
);

});

0 comments on commit e12fb92

Please sign in to comment.