Skip to content

Commit ac96b00

Browse files
authored
Merge pull request #29 from launchdarkly/ag/ch10894/fix-promise-interface
[ch1089] Fix promise interface
2 parents 927baad + 7d13ef6 commit ac96b00

File tree

3 files changed

+85
-30
lines changed

3 files changed

+85
-30
lines changed

src/__tests__/utils-test.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
var assert = require('assert');
2+
var wrapPromiseCallback = require('../utils.js').wrapPromiseCallback;
3+
4+
describe('utils', function() {
5+
describe('wrapPromiseCallback', function() {
6+
it('should resolve to the value', function(done) {
7+
const promise = wrapPromiseCallback(Promise.resolve('woohoo'));
8+
promise.then(function(value) {
9+
expect(value).to.equal('woohoo');
10+
done();
11+
});
12+
});
13+
14+
it('should reject with the error', function(done) {
15+
const error = new Error('something went wrong');
16+
const promise = wrapPromiseCallback(Promise.reject(error));
17+
promise.catch(function(error) {
18+
expect(error).to.equal(error);
19+
done();
20+
});
21+
});
22+
23+
it('should call the callback with a value if the promise resolves', function(done) {
24+
const callback = sinon.spy();
25+
const promise = wrapPromiseCallback(Promise.resolve('woohoo'), callback);
26+
27+
promise.then(function(result) {
28+
expect(result).to.equal('woohoo');
29+
// callback run on next tick to maintain asynchronous expections
30+
setTimeout(function() {
31+
expect(callback.calledWith(null, 'woohoo')).to.be.true;
32+
done();
33+
}, 0);
34+
});
35+
});
36+
37+
it('should call the callback with an error if the promise rejects', function(done) {
38+
const error = new Error('something went wrong');
39+
const callback = sinon.spy();
40+
const promise = wrapPromiseCallback(Promise.reject(error), callback);
41+
42+
promise.catch(function(v) {
43+
expect(v).to.equal(error);
44+
// callback run on next tick to maintain asynchronous expections
45+
setTimeout(function() {
46+
expect(callback.calledWith(error, null)).to.be.true;
47+
done();
48+
}, 0);
49+
});
50+
});
51+
});
52+
});

src/index.js

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,6 @@ var flushInterval = 2000;
3434

3535
var seenRequests = {};
3636

37-
/**
38-
* Wrap a promise to invoke an optional callback upon resolution or rejection.
39-
*
40-
* This function assumes the callback follows the Node.js callback type: (err, value) => void
41-
*
42-
* If a callback is provided:
43-
* - if the promise is resolved, invoke the callback with (null, value)
44-
* - if the promise is rejected, invoke the callback with (error, null)
45-
*
46-
* @param {Promise<any>} promise
47-
* @param {Function} callback
48-
* @returns Promise<any>
49-
*/
50-
function wrapPromiseCallback(promise, callback) {
51-
if (callback) {
52-
return promise.then(
53-
function(value) {
54-
setTimeout(function() { callback(null, value); }, 0);
55-
},
56-
function(error) {
57-
setTimeout(function() { callback(error, null); }, 0);
58-
}
59-
);
60-
}
61-
62-
return promise;
63-
}
64-
6537
function sendIdentifyEvent(user) {
6638
enqueueEvent({
6739
kind: 'identify',
@@ -116,7 +88,7 @@ function waitUntilReady() {
11688
}
11789

11890
function identify(user, hash, onDone) {
119-
return wrapPromiseCallback(new Promise((function(resolve, reject) {
91+
return utils.wrapPromiseCallback(new Promise((function(resolve, reject) {
12092
ident.setUser(user);
12193
requestor.fetchFlagSettings(ident.getUser(), hash, function(err, settings) {
12294
if (err) {

src/utils.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,41 @@ function merge(target, varArgs) { // .length of function is 2
5555
return to;
5656
}
5757

58+
/**
59+
* Wrap a promise to invoke an optional callback upon resolution or rejection.
60+
*
61+
* This function assumes the callback follows the Node.js callback type: (err, value) => void
62+
*
63+
* If a callback is provided:
64+
* - if the promise is resolved, invoke the callback with (null, value)
65+
* - if the promise is rejected, invoke the callback with (error, null)
66+
*
67+
* @param {Promise<any>} promise
68+
* @param {Function} callback
69+
* @returns Promise<any>
70+
*/
71+
function wrapPromiseCallback(promise, callback) {
72+
return promise.then(
73+
function(value) {
74+
if (callback) {
75+
setTimeout(function() { callback(null, value); }, 0);
76+
}
77+
return value;
78+
},
79+
function(error) {
80+
if (callback) {
81+
setTimeout(function() { callback(error, null); }, 0);
82+
}
83+
return Promise.reject(error);
84+
}
85+
);
86+
}
87+
5888
module.exports = {
5989
btoa: btoa,
6090
base64URLEncode: base64URLEncode,
6191
clone: clone,
6292
modifications: modifications,
63-
merge: merge
93+
merge: merge,
94+
wrapPromiseCallback: wrapPromiseCallback
6495
};

0 commit comments

Comments
 (0)