Skip to content

Commit dad3406

Browse files
authored
Merge pull request #330 from bertho-zero/async
async/await + minor changes
2 parents e05b81f + 741df73 commit dad3406

File tree

19 files changed

+268
-266
lines changed

19 files changed

+268
-266
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ npm-debug.log
1010
.happypack
1111
webpack/dlls/*.json
1212
api/**/*.nedb
13-
*.report.html
13+
*.report.html
14+
coverage

api/actions/__tests__/widget-load-test.js

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,15 @@ describe('widget load', () => {
1414
sinon.stub(Math, 'random').returns(0.4);
1515
});
1616

17-
it('uses the widgets from the session', () => {
18-
load({ session: { user: {}, widgets: ['a', 'b', 'c'] } }, undefined).then(widgets => {
19-
expect(widgets.length).to.equal(3);
20-
});
17+
it('uses the widgets from the session', async () => {
18+
const widgets = await load({ session: { user: {}, widgets: ['a', 'b', 'c'] } }, undefined);
19+
expect(widgets.length).to.equal(3);
2120
});
2221

23-
it('initializes the widgets ', () => {
24-
load({ session: { user: {} } }, undefined).then(widgets => {
25-
expect(widgets.length).to.equal(4);
26-
expect(widgets[0].color).to.equal('Red');
27-
});
22+
it('initializes the widgets ', async () => {
23+
const widgets = await load({ session: { user: {} } }, undefined);
24+
expect(widgets.length).to.equal(4);
25+
expect(widgets[0].color).to.equal('Red');
2826
});
2927
});
3028

@@ -33,13 +31,12 @@ describe('widget load', () => {
3331
sinon.stub(Math, 'random').returns(0.2);
3432
});
3533

36-
it('rejects the call', () => {
37-
load({ session: { user: {} } }, undefined).then(
38-
() => {},
39-
err => {
40-
expect(err).to.equal('Widget load fails 33% of the time. You were unlucky.');
41-
}
42-
);
34+
it('rejects the call', async () => {
35+
try {
36+
await load({ session: { user: {} } }, undefined);
37+
} catch (err) {
38+
expect(err).to.equal('Widget load fails 33% of the time. You were unlucky.');
39+
}
4340
});
4441
});
4542
});

api/actions/__tests__/widget-update-test.js

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,30 @@ describe('widget update', () => {
2323
}
2424
});
2525

26-
it('does not accept green widgets', () => {
26+
it('does not accept green widgets', async () => {
2727
sinon.stub(load, 'default').resolves(widgets);
28-
return update({ session: {}, body: { color: 'Green' } }).then(
29-
() => {},
30-
err => {
31-
expect(err.color).to.equal('We do not accept green widgets');
32-
}
33-
);
28+
try {
29+
await update({ session: {}, body: { color: 'Green' } });
30+
} catch (err) {
31+
expect(err.color).to.equal('We do not accept green widgets');
32+
}
3433
});
3534

36-
it('fails to load widgets', () => {
35+
it('fails to load widgets', async () => {
3736
sinon.stub(load, 'default').rejects(new Error('Widget fail to load.'));
38-
return update({ session: {}, body: { color: 'Blue' } }).then(
39-
() => {},
40-
err => {
41-
expect(err.message).to.equal('Widget fail to load.');
42-
}
43-
);
37+
try {
38+
await update({ session: {}, body: { color: 'Blue' } });
39+
} catch (err) {
40+
expect(err.message).to.equal('Widget fail to load.');
41+
}
4442
});
4543

46-
it('updates a widget', () => {
44+
it('updates a widget', async () => {
4745
sinon.stub(load, 'default').resolves(widgets);
4846
const widget = { id: 2, color: 'Blue' };
49-
return update({ session: {}, body: widget }).then(res => {
50-
expect(res).to.deep.equal(widget);
51-
expect(widgets[1]).to.deep.equal(widget);
52-
});
47+
const res = await update({ session: {}, body: widget });
48+
expect(res).to.deep.equal(widget);
49+
expect(widgets[1]).to.deep.equal(widget);
5350
});
5451
});
5552

@@ -58,13 +55,12 @@ describe('widget update', () => {
5855
sinon.stub(Math, 'random').returns(0.1);
5956
});
6057

61-
it('rejects the call in 20% of the time', () => {
62-
update().then(
63-
() => {},
64-
err => {
65-
expect(err).to.equal('Oh no! Widget save fails 20% of the time. Try again.');
66-
}
67-
);
58+
it('rejects the call in 20% of the time', async () => {
59+
try {
60+
update();
61+
} catch (err) {
62+
expect(err).to.equal('Oh no! Widget save fails 20% of the time. Try again.');
63+
}
6864
});
6965
});
7066
});

api/actions/widget/update.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,27 @@ import load from './load';
33
export default function update(req) {
44
return new Promise((resolve, reject) => {
55
// write to database
6-
setTimeout(() => {
6+
setTimeout(async () => {
77
if (Math.random() < 0.2) {
88
reject('Oh no! Widget save fails 20% of the time. Try again.');
99
} else {
10-
load(req).then(
11-
data => {
12-
const widgets = data;
13-
const widget = req.body;
14-
if (widget.color === 'Green') {
15-
reject({
16-
color: 'We do not accept green widgets' // example server-side validation error
17-
});
18-
}
19-
if (widget.id) {
20-
widgets[widget.id - 1] = widget; // id is 1-based. please don't code like this in production! :-)
21-
req.session.widgets = widgets;
22-
}
23-
resolve(widget);
24-
},
25-
err => {
26-
reject(err);
10+
try {
11+
const data = await load(req);
12+
const widgets = data;
13+
const widget = req.body;
14+
if (widget.color === 'Green') {
15+
reject({
16+
color: 'We do not accept green widgets' // example server-side validation error
17+
});
2718
}
28-
);
19+
if (widget.id) {
20+
widgets[widget.id - 1] = widget; // id is 1-based. please don't code like this in production! :-)
21+
req.session.widgets = widgets;
22+
}
23+
resolve(widget);
24+
} catch (err) {
25+
reject(err);
26+
}
2927
}
3028
}, 1500); // simulate async db write
3129
});

api/api.js

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import cookieParser from 'cookie-parser';
66
import hooks from 'feathers-hooks';
77
import rest from 'feathers-rest';
88
import socketio from 'feathers-socketio';
9-
import isPromise from 'is-promise';
109
import PrettyError from 'pretty-error';
1110
import config from './config';
1211
import middleware from './middleware';
@@ -35,7 +34,7 @@ app
3534
.use(bodyParser.urlencoded({ extended: true }))
3635
.use(bodyParser.json());
3736

38-
const actionsHandler = (req, res, next) => {
37+
const actionsHandler = async (req, res, next) => {
3938
const splittedUrlPath = req.url
4039
.split('?')[0]
4140
.split('/')
@@ -44,31 +43,28 @@ const actionsHandler = (req, res, next) => {
4443

4544
req.app = app;
4645

47-
const catchError = error => {
46+
const catchError = async error => {
4847
console.error('API ERROR:', pretty.render(error));
4948
res.status(error.status || 500).json(error);
5049
};
5150

5251
if (action) {
5352
try {
54-
const handle = action(req, params);
55-
(isPromise(handle) ? handle : Promise.resolve(handle))
56-
.then(result => {
57-
if (result instanceof Function) {
58-
result(res);
59-
} else {
60-
res.json(result);
61-
}
62-
})
63-
.catch(reason => {
64-
if (reason && reason.redirect) {
65-
res.redirect(reason.redirect);
66-
} else {
67-
catchError(reason);
68-
}
69-
});
53+
try {
54+
const result = await action(req, params);
55+
if (result instanceof Function) {
56+
result(res);
57+
} else {
58+
res.json(result);
59+
}
60+
} catch (reason) {
61+
if (reason && reason.redirect) {
62+
return res.redirect(reason.redirect);
63+
}
64+
return catchError(reason);
65+
}
7066
} catch (error) {
71-
catchError(error);
67+
return catchError(error);
7268
}
7369
} else {
7470
next();

api/hooks/validateHook.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import errors from 'feathers-errors';
22
import { createAsyncValidator as validator } from 'utils/validation';
33

44
export default function validateHook(schema) {
5-
return hook =>
6-
validator(schema, { hook })(hook.data)
7-
.then(() => hook)
8-
.catch(errorsValidation => {
9-
if (Object.keys(errorsValidation).length) {
10-
throw new errors.BadRequest('Validation failed', errorsValidation);
11-
}
12-
});
5+
return async hook => {
6+
try {
7+
await validator(schema, { hook })(hook.data);
8+
return hook;
9+
} catch (errorsValidation) {
10+
if (Object.keys(errorsValidation).length) {
11+
throw new errors.BadRequest('Validation failed', errorsValidation);
12+
}
13+
}
14+
};
1315
}

api/services/authentication/index.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ import { discard } from 'feathers-hooks-common';
99
export socketAuth from './socketAuth';
1010

1111
function populateUser(authConfig) {
12-
return hook =>
13-
hook.app.passport
14-
.verifyJWT(hook.result.accessToken, authConfig)
15-
.then(payload => hook.app.service('users').get(payload.userId))
16-
.then(user => {
17-
hook.result.user = user;
18-
});
12+
return async hook => {
13+
const payload = await hook.app.passport.verifyJWT(hook.result.accessToken, authConfig);
14+
const user = await hook.app.service('users').get(payload.userId);
15+
hook.result.user = user;
16+
};
1917
}
2018

2119
function restToSocketAuth() {
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export default function socketAuth(app) {
2-
return (socket, next) => {
2+
return async (socket, next) => {
33
const { cookie } = socket.request.headers;
44
const cookies =
55
cookie &&
@@ -17,17 +17,17 @@ export default function socketAuth(app) {
1717

1818
if (!accessToken) return next();
1919

20-
app.passport
21-
.verifyJWT(accessToken, app.get('auth'))
22-
.then(payload => app.service('users').get(payload.userId))
23-
.then(user => {
24-
Object.assign(socket.feathers, {
25-
accessToken,
26-
user,
27-
authenticated: true
28-
});
29-
next();
30-
})
31-
.catch(() => next());
20+
try {
21+
const payload = await app.passport.verifyJWT(accessToken, app.get('auth'));
22+
const user = await app.service('users').get(payload.userId);
23+
Object.assign(socket.feathers, {
24+
accessToken,
25+
user,
26+
authenticated: true
27+
});
28+
next();
29+
} catch (e) {
30+
next();
31+
}
3232
};
3333
}

api/utils/validation.js

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,33 @@
1-
import isPromise from 'is-promise';
21
import * as validation from '../../src/utils/validation';
32

43
function createAsyncValidator(rules, params) {
5-
return (data = {}) => {
4+
return async (data = {}) => {
65
const errors = validation.createValidator(rules, params)(data);
76

8-
const promises = Object.keys(errors).map(name => {
9-
const error = errors[name];
10-
const myResolve = () => ({ status: 'resolved', name });
11-
const myReject = err => ({ status: 'rejected', name, error: err });
12-
13-
if (isPromise(error)) {
14-
return error.then(myResolve).catch(myReject);
7+
const finalErrors = await Object.keys(errors).reduce(async (result, name) => {
8+
try {
9+
const error = await errors[name];
10+
return error ? Object.assign(result, { [name]: error }) : result;
11+
} catch (error) {
12+
return Object.assign(result, { [name]: error });
1513
}
14+
}, {});
1615

17-
return error ? myReject() : myResolve();
18-
});
19-
20-
return Promise.all(promises).then(results => {
21-
const finalErrors = results
22-
.filter(x => x.status === 'rejected')
23-
.reduce((prev, next) => ({ ...prev, [next.name]: next.error }), {});
16+
if (Object.keys(finalErrors).length) {
17+
throw finalErrors;
18+
}
2419

25-
return Object.keys(finalErrors).length ? Promise.reject(finalErrors) : Promise.resolve(data);
26-
});
20+
return data;
2721
};
2822
}
2923

3024
function unique(field) {
31-
return (value, data, { hook }) =>
32-
hook.service.find({ query: { [field]: value } }).then(result => {
33-
if (result.total !== 0) {
34-
return Promise.reject('Already exist');
35-
}
36-
});
25+
return async (value, data, { hook }) => {
26+
const result = await hook.service.find({ query: { [field]: value } });
27+
if (result.total !== 0) {
28+
return Promise.reject('Already exist');
29+
}
30+
};
3731
}
3832

3933
module.exports = {

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@
149149
"feathers-rest": "^1.7.3",
150150
"feathers-socketio": "^2.0.0",
151151
"http-proxy": "^1.16.2",
152-
"is-promise": "^2.1.0",
153152
"js-cookie": "^2.1.3",
154153
"localforage": "^1.4.3",
155154
"lru-memoize": "^1.0.1",

0 commit comments

Comments
 (0)