Skip to content

Commit

Permalink
feat(promise): add promise interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Marton committed Oct 10, 2017
1 parent bbdeb79 commit 8dd9b80
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 26 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ restify HTTP errors). If `obj` looks like a `RestError`:
then `err` gets "upconverted" into a `RestError` for you. Otherwise
it will be an `HttpError`.

**Promise interface:**

Without passing a callback as a last parameter to the method call, it returns
a Promise.

This returned Promise will be resolved with the same arguments as the callback
version would, except that arguments will be wrapped in an object, for example:

```js
client.get('/foo/bar')
.then(function({ req, res, obj }) {})
.catch(function(err) {});
```

#### createJsonClient(options)

```javascript
Expand Down Expand Up @@ -228,6 +242,20 @@ the source for `JsonClient`. Effectively, you extend it, and set the
appropriate options in the constructor and implement a `write` (for
put/post) and `parse` method (for all HTTP bodies), and that's it.

**Promise interface:**

Without passing a callback as a last parameter to the method call, it returns
a Promise.

This returned Promise will be resolved with the same arguments as the callback
version would, except that arguments will be wrapped in an object, for example:

```js
client.get('/foo/bar')
.then(function({ req, res, data }) {})
.catch(function(err) {});
```

#### createStringClient(options)

```javascript
Expand Down
83 changes: 80 additions & 3 deletions lib/StringClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,55 @@ var zlib = require('zlib');
var assert = require('assert-plus');
var qs = require('querystring');
var util = require('util');
var Promise = require('es6-promise');

var HttpClient = require('./HttpClient');

/**
* Returns a Promise when callback fn is undefined
* @function promisify
* @returns {Promise|*}
*/
function promisify () {
var args = Array.prototype.slice.call(arguments);
var fn = args.shift();
var _this = this;

assert.func(fn, 'args[0]');

// Is callback presented?
if (typeof args[args.length - 1] === 'function') {
return (fn.apply(this, args));
}

return new Promise(function (resolve, reject) {
// callback is passed as last argument (undefined)
args[args.length - 1] = function (err, req, res, data) {
if (err) {
reject(err);
return;
}

var result = {
req: req,
res: res
};

if (data) {
if (_this.constructor.name === 'JsonClient') {
result.obj = data;
} else {
result.data = data;
}
}

resolve(result);
}

fn.apply(_this, args);
});
}


// --- API

Expand Down Expand Up @@ -57,27 +103,58 @@ function normalizeArgs(arg1, arg2, arg3) {
};
}

StringClient.prototype.del = function del(options, callback) {
var opts = this._options('DELETE', options);
var read = promisify.bind(this, this.read);
return (read(opts, callback));
};


StringClient.prototype.get = function get(options, callback) {
var opts = this._options('GET', options);
var read = promisify.bind(this, this.read);
return (read(opts, callback));
};


StringClient.prototype.head = function head(options, callback) {
var opts = this._options('HEAD', options);
var read = promisify.bind(this, this.read);
return (read(opts, callback));
};


StringClient.prototype.opts = function httpOptions(options, callback) {
var opts = this._options('OPTIONS', options);
var read = promisify.bind(this, this.read);
return (read(opts, callback));
};


StringClient.prototype.post = function post(options, body, callback) {
var opts = this._options('POST', options);
var write = promisify.bind(this, this.write);

var args = normalizeArgs.apply(null, arguments);
return (this.write(opts, args.body, args.callback));
return (write(opts, args.body, args.callback));
};


StringClient.prototype.put = function put(options, body, callback) {
var opts = this._options('PUT', options);
var write = promisify.bind(this, this.write);

var args = normalizeArgs.apply(null, arguments);
return (this.write(opts, args.body, args.callback));
return (write(opts, args.body, args.callback));
};


StringClient.prototype.patch = function patch(options, body, callback) {
var opts = this._options('PATCH', options);
var write = promisify.bind(this, this.write);

var args = normalizeArgs.apply(null, arguments);
return (this.write(opts, args.body, args.callback));
return (write(opts, args.body, args.callback));
};


Expand Down
51 changes: 28 additions & 23 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"assert-plus": "^1.0.0",
"backoff": "^2.4.1",
"bunyan": "^1.8.3",
"es6-promise": "4.1.1",
"fast-safe-stringify": "^1.1.3",
"keep-alive-agent": "0.0.1",
"lodash": "^4.7.0",
Expand Down
29 changes: 29 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,15 @@ describe('restify-client tests', function () {
});
});

it('GET json via Promise interface', function () {
return JSON_CLIENT.get('/json/mcavage')
.then(function (result) {
assert.ok(result.req);
assert.ok(result.res);
assert.deepEqual(result.obj, {hello: 'mcavage'});
});
});

it('GH-778 GET jsonp', function (done) {
// Using variables here to keep lines under 80 chars
var jsonpUrl = '/json/jsonp?callback=testCallback';
Expand Down Expand Up @@ -354,6 +363,16 @@ describe('restify-client tests', function () {
});
});

it('POST json via Promise interface', function () {
var data = { hello: 'foo' };
return JSON_CLIENT.post('/json/mcavage', data)
.then(function (result) {
assert.ok(result.req);
assert.ok(result.res);
assert.deepEqual(result.obj, {hello: 'foo'});
});
});

it('POST with circular JSON', function (done) {
var data = {
hello: 'foo'
Expand Down Expand Up @@ -463,6 +482,16 @@ describe('restify-client tests', function () {
});
});

it('GET text via Promise interface', function () {
return STR_CLIENT.get('/str/mcavage')
.then(function (result) {
assert.ok(result.req);
assert.ok(result.res);
assert.equal(result.res.body, result.data);
assert.equal(result.data, 'hello mcavage');
});
});

it('GET PARTIAL text', function (done) {
var opts = {
path: '/str/mcavage',
Expand Down

0 comments on commit 8dd9b80

Please sign in to comment.