Skip to content

Commit f5941fc

Browse files
committed
partial move to async / await
1 parent b6d1204 commit f5941fc

File tree

12 files changed

+211
-207
lines changed

12 files changed

+211
-207
lines changed

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

Lines changed: 12 additions & 15 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

@@ -34,12 +32,11 @@ describe('widget load', () => {
3432
});
3533

3634
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-
);
35+
try {
36+
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/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: 20 additions & 21 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,37 +34,37 @@ app
3534
.use(bodyParser.urlencoded({ extended: true }))
3635
.use(bodyParser.json());
3736

38-
const actionsHandler = (req, res, next) => {
39-
const splittedUrlPath = req.url.split('?')[0].split('/').slice(1);
37+
const actionsHandler = async (req, res, next) => {
38+
const splittedUrlPath = req.url
39+
.split('?')[0]
40+
.split('/')
41+
.slice(1);
4042
const { action, params } = mapUrl(actions, splittedUrlPath);
4143

4244
req.app = app;
4345

44-
const catchError = error => {
46+
const catchError = async error => {
4547
console.error('API ERROR:', pretty.render(error));
4648
res.status(error.status || 500).json(error);
4749
};
4850

4951
if (action) {
5052
try {
51-
const handle = action(req, params);
52-
(isPromise(handle) ? handle : Promise.resolve(handle))
53-
.then(result => {
54-
if (result instanceof Function) {
55-
result(res);
56-
} else {
57-
res.json(result);
58-
}
59-
})
60-
.catch(reason => {
61-
if (reason && reason.redirect) {
62-
res.redirect(reason.redirect);
63-
} else {
64-
catchError(reason);
65-
}
66-
});
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+
}
6766
} catch (error) {
68-
catchError(error);
67+
return catchError(error);
6968
}
7069
} else {
7170
next();

api/hooks/validateHook.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +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).then(() => hook).catch(errorsValidation => {
5+
return async hook => {
6+
try {
7+
await validator(schema, { hook })(hook.data);
8+
return hook;
9+
} catch (errorsValidation) {
710
if (Object.keys(errorsValidation).length) {
811
throw new errors.BadRequest('Validation failed', errorsValidation);
912
}
10-
});
13+
}
14+
};
1115
}

api/utils/validation.js

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
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 }), {});
24-
25-
return Object.keys(finalErrors).length ? Promise.reject(finalErrors) : Promise.resolve(data);
26-
});
16+
return (await Object.keys(finalErrors).length) ? Promise.reject(finalErrors) : data;
2717
};
2818
}
2919

src/containers/ChatFeathers/ChatFeathers.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,17 @@ export default class ChatFeathers extends Component {
4949
this.props.app.service('messages').removeListener('created', this.props.addMessage);
5050
}
5151

52-
handleSubmit = event => {
52+
handleSubmit = async event => {
5353
event.preventDefault();
54-
this.props.app
55-
.service('messages')
56-
.create({ text: this.state.message })
57-
.then(() => this.setState({ message: '', error: false }))
58-
.catch(error => {
59-
console.log(error);
60-
this.setState({ error: error.message || false });
61-
});
54+
55+
try {
56+
await this.props.app.service('messages').create({ text: this.state.message });
57+
58+
this.setState({ message: '', error: false });
59+
} catch (error) {
60+
console.log(error);
61+
this.setState({ error: error.message || false });
62+
}
6263
};
6364

6465
render() {
@@ -69,14 +70,14 @@ export default class ChatFeathers extends Component {
6970
<div className="container">
7071
<h1>Chat</h1>
7172

72-
{user &&
73+
{user && (
7374
<div>
7475
<ul>
75-
{messages.map(msg =>
76-
(<li key={`chat.msg.${msg._id}`}>
76+
{messages.map(msg => (
77+
<li key={`chat.msg.${msg._id}`}>
7778
{msg.sentBy.email}: {msg.text}
78-
</li>)
79-
)}
79+
</li>
80+
))}
8081
</ul>
8182
<form onSubmit={this.handleSubmit}>
8283
<input
@@ -91,12 +92,10 @@ export default class ChatFeathers extends Component {
9192
<button className="btn" onClick={this.handleSubmit}>
9293
Send
9394
</button>
94-
{error &&
95-
<div className="text-danger">
96-
{error}
97-
</div>}
95+
{error && <div className="text-danger">{error}</div>}
9896
</form>
99-
</div>}
97+
</div>
98+
)}
10099
</div>
101100
);
102101
}

src/containers/Login/Login.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,26 @@ export default class Login extends Component {
2626
router: PropTypes.object
2727
};
2828

29-
onFacebookLogin = (err, data) => {
29+
onFacebookLogin = async (err, data) => {
3030
if (err) return;
31-
this.props.login('facebook', data, false).then(this.successLogin).catch(error => {
31+
32+
try {
33+
const result = await this.props.login('facebook', data, false);
34+
this.successLogin(result);
35+
} catch (error) {
3236
if (error.message === 'Incomplete oauth registration') {
3337
this.context.router.push({
3438
pathname: '/register',
3539
state: { oauth: error.data }
3640
});
3741
}
38-
});
42+
}
3943
};
4044

41-
login = data => this.props.login('local', data).then(this.successLogin);
45+
login = async data => {
46+
const result = await this.props.login('local', data);
47+
return this.successLogin(result);
48+
};
4249

4350
successLogin = data => {
4451
this.props.notifSend({
@@ -49,18 +56,19 @@ export default class Login extends Component {
4956
return data;
5057
};
5158

52-
FacebookLoginButton = ({ facebookLogin }) =>
53-
(<button className="btn btn-primary" onClick={facebookLogin}>
59+
FacebookLoginButton = ({ facebookLogin }) => (
60+
<button className="btn btn-primary" onClick={facebookLogin}>
5461
Login with <i className="fa fa-facebook-f" />
55-
</button>);
62+
</button>
63+
);
5664

5765
render() {
5866
const { user, logout } = this.props;
5967
return (
6068
<div className="container">
6169
<Helmet title="Login" />
6270
<h1>Login</h1>
63-
{!user &&
71+
{!user && (
6472
<div>
6573
<LoginForm onSubmit={this.login} />
6674
<p>This will "log you in" as this user, storing the username in the session of the API server.</p>
@@ -71,19 +79,19 @@ export default class Login extends Component {
7179
onLogin={this.onFacebookLogin}
7280
component={this.FacebookLoginButton}
7381
/>
74-
</div>}
75-
{user &&
82+
</div>
83+
)}
84+
{user && (
7685
<div>
77-
<p>
78-
You are currently logged in as {user.email}.
79-
</p>
86+
<p>You are currently logged in as {user.email}.</p>
8087

8188
<div>
8289
<button className="btn btn-danger" onClick={logout}>
8390
<i className="fa fa-sign-out" /> Log Out
8491
</button>
8592
</div>
86-
</div>}
93+
</div>
94+
)}
8795
</div>
8896
);
8997
}

src/containers/Register/Register.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ export default class Register extends Component {
2121
return location.state && location.state.oauth;
2222
};
2323

24-
register = data => this.props.register(data).then(this.successRegister);
24+
register = async data => {
25+
const result = await this.props.register(data);
26+
return this.successRegister(result);
27+
};
2528

2629
successRegister = result => {
2730
this.props.notifSend({

0 commit comments

Comments
 (0)