Skip to content

Commit a54c7e1

Browse files
committed
Auto merge of #2378 - Turbo87:tasks, r=locks
Convert async actions on components to tasks async actions are dangerous because they reference component instances that might have already been destroyed when the async behavior finishes. ember-concurrency tasks resolve this issue by cancelling themselves if the parent object is destroyed. r? @locks
2 parents 1c7a11c + 8ba7571 commit a54c7e1

File tree

6 files changed

+80
-78
lines changed

6 files changed

+80
-78
lines changed

app/components/api-token-row.hbs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@disabled={{this.api_token.isSaving}}
88
@value={{this.api_token.name}}
99
@autofocus="autofocus"
10-
@enter={{action "saveToken"}}
10+
@enter={{action (perform this.saveTokenTask)}}
1111
data-test-focused-input
1212
/>
1313
{{else}}
@@ -38,7 +38,7 @@
3838
disabled={{this.disableCreate}}
3939
title={{if this.emptyName "You must specify a name" ""}}
4040
data-test-save-token-button
41-
{{action "saveToken"}}
41+
{{action (perform this.saveTokenTask)}}
4242
>
4343
Create
4444
</button>
@@ -48,7 +48,7 @@
4848
local-class="revoke-button"
4949
disabled={{this.api_token.isSaving}}
5050
data-test-revoke-token-button
51-
{{action "revokeToken"}}
51+
{{action (perform this.revokeTokenTask)}}
5252
>
5353
Revoke
5454
</button>

app/components/api-token-row.js

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import Component from '@ember/component';
22
import { empty, or } from '@ember/object/computed';
33

4+
import { task } from 'ember-concurrency';
5+
46
export default Component.extend({
57
emptyName: empty('api_token.name'),
68
disableCreate: or('api_token.isSaving', 'emptyName'),
@@ -13,34 +15,32 @@ export default Component.extend({
1315
}
1416
},
1517

16-
actions: {
17-
async saveToken() {
18-
try {
19-
await this.api_token.save();
20-
this.set('serverError', null);
21-
} catch (err) {
22-
let msg;
23-
if (err.errors && err.errors[0] && err.errors[0].detail) {
24-
msg = `An error occurred while saving this token, ${err.errors[0].detail}`;
25-
} else {
26-
msg = 'An unknown error occurred while saving this token';
27-
}
28-
this.set('serverError', msg);
18+
saveTokenTask: task(function* () {
19+
try {
20+
yield this.api_token.save();
21+
this.set('serverError', null);
22+
} catch (err) {
23+
let msg;
24+
if (err.errors && err.errors[0] && err.errors[0].detail) {
25+
msg = `An error occurred while saving this token, ${err.errors[0].detail}`;
26+
} else {
27+
msg = 'An unknown error occurred while saving this token';
2928
}
30-
},
29+
this.set('serverError', msg);
30+
}
31+
}),
3132

32-
async revokeToken() {
33-
try {
34-
await this.api_token.destroyRecord();
35-
} catch (err) {
36-
let msg;
37-
if (err.errors && err.errors[0] && err.errors[0].detail) {
38-
msg = `An error occurred while revoking this token, ${err.errors[0].detail}`;
39-
} else {
40-
msg = 'An unknown error occurred while revoking this token';
41-
}
42-
this.set('serverError', msg);
33+
revokeTokenTask: task(function* () {
34+
try {
35+
yield this.api_token.destroyRecord();
36+
} catch (err) {
37+
let msg;
38+
if (err.errors && err.errors[0] && err.errors[0].detail) {
39+
msg = `An error occurred while revoking this token, ${err.errors[0].detail}`;
40+
} else {
41+
msg = 'An unknown error occurred while revoking this token';
4342
}
44-
},
45-
},
43+
this.set('serverError', msg);
44+
}
45+
}),
4646
});

app/components/email-input.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
<p>Your email has not yet been verified.</p>
5353
</div>
5454
<div local-class="actions">
55-
<button type="button" local-class="resend-button" {{action 'resendEmail'}} disabled={{this.disableResend}}>
55+
<button type="button" local-class="resend-button" {{action (perform this.resendEmailTask)}} disabled={{this.disableResend}}>
5656
{{this.resendButtonText}}
5757
</button>
5858
</div>

app/components/email-input.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { empty } from '@ember/object/computed';
33
import { computed } from '@ember/object';
44
import { inject as service } from '@ember/service';
55

6+
import { task } from 'ember-concurrency';
7+
68
import ajax from '../utils/ajax';
79

810
export default Component.extend({
@@ -42,6 +44,23 @@ export default Component.extend({
4244
}
4345
}),
4446

47+
resendEmailTask: task(function* () {
48+
let user = this.user;
49+
50+
try {
51+
yield ajax(`/api/v1/users/${user.id}/resend`, { method: 'PUT' });
52+
this.set('disableResend', true);
53+
} catch (error) {
54+
if (error.errors) {
55+
this.set('isError', true);
56+
this.set('emailError', `Error in resending message: ${error.errors[0].detail}`);
57+
} else {
58+
this.set('isError', true);
59+
this.set('emailError', 'Unknown error in resending message');
60+
}
61+
}
62+
}),
63+
4564
actions: {
4665
editEmail() {
4766
let email = this.value;
@@ -97,22 +116,5 @@ export default Component.extend({
97116
this.set('isEditing', false);
98117
this.set('value', this.prevEmail);
99118
},
100-
101-
async resendEmail() {
102-
let user = this.user;
103-
104-
try {
105-
await ajax(`/api/v1/users/${user.id}/resend`, { method: 'PUT' });
106-
this.set('disableResend', true);
107-
} catch (error) {
108-
if (error.errors) {
109-
this.set('isError', true);
110-
this.set('emailError', `Error in resending message: ${error.errors[0].detail}`);
111-
} else {
112-
this.set('isError', true);
113-
this.set('emailError', 'Unknown error in resending message');
114-
}
115-
}
116-
},
117119
},
118120
});

app/components/pending-owner-invite-row.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
{{moment-from-now this.invite.created_at}}
3030
</div>
3131
<div>
32-
<button type="button" local-class="accept-button" data-test-accept-button {{action 'acceptInvitation' this.invite}}>Accept</button>
33-
<button type="button" local-class="decline-button" data-test-decline-button {{action 'declineInvitation' this.invite}}>Decline</button>
32+
<button type="button" local-class="accept-button" data-test-accept-button {{action (perform this.acceptInvitationTask)}}>Accept</button>
33+
<button type="button" local-class="decline-button" data-test-decline-button {{action (perform this.declineInvitationTask)}}>Decline</button>
3434
</div>
3535
{{#if this.isError}}
3636
<p local-class="error-message" data-test-error-message>{{this.inviteError}}</p>
Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
11
import Component from '@ember/component';
22

3+
import { task } from 'ember-concurrency';
4+
35
export default Component.extend({
46
tagName: '',
57
isAccepted: false,
68
isDeclined: false,
79
isError: false,
810
inviteError: 'default error message',
911

10-
actions: {
11-
async acceptInvitation(invite) {
12-
invite.set('accepted', true);
12+
acceptInvitationTask: task(function* () {
13+
this.invite.set('accepted', true);
1314

14-
try {
15-
await invite.save();
16-
this.set('isAccepted', true);
17-
} catch (error) {
18-
this.set('isError', true);
19-
if (error.errors) {
20-
this.set('inviteError', `Error in accepting invite: ${error.errors[0].detail}`);
21-
} else {
22-
this.set('inviteError', 'Error in accepting invite');
23-
}
15+
try {
16+
yield this.invite.save();
17+
this.set('isAccepted', true);
18+
} catch (error) {
19+
this.set('isError', true);
20+
if (error.errors) {
21+
this.set('inviteError', `Error in accepting invite: ${error.errors[0].detail}`);
22+
} else {
23+
this.set('inviteError', 'Error in accepting invite');
2424
}
25-
},
25+
}
26+
}),
2627

27-
async declineInvitation(invite) {
28-
invite.set('accepted', false);
28+
declineInvitationTask: task(function* () {
29+
this.invite.set('accepted', false);
2930

30-
try {
31-
await invite.save();
32-
this.set('isDeclined', true);
33-
} catch (error) {
34-
this.set('isError', true);
35-
if (error.errors) {
36-
this.set('inviteError', `Error in declining invite: ${error.errors[0].detail}`);
37-
} else {
38-
this.set('inviteError', 'Error in declining invite');
39-
}
31+
try {
32+
yield this.invite.save();
33+
this.set('isDeclined', true);
34+
} catch (error) {
35+
this.set('isError', true);
36+
if (error.errors) {
37+
this.set('inviteError', `Error in declining invite: ${error.errors[0].detail}`);
38+
} else {
39+
this.set('inviteError', 'Error in declining invite');
4040
}
41-
},
42-
},
41+
}
42+
}),
4343
});

0 commit comments

Comments
 (0)