Skip to content

Commit 33c4597

Browse files
authored
After save details (#578)
* updates to dependencies to get working locally? * Try to improve afterSave documentation to include: 1. How to ensure that afterSave runs async if necessary 2. That request.context is a feature and how to use it. I also added a real world code example that uses modern javascript.
1 parent 3c7f1bb commit 33c4597

File tree

3 files changed

+1238
-1203
lines changed

3 files changed

+1238
-1203
lines changed

Gemfile.lock

Lines changed: 94 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
activesupport (4.2.9)
4+
activesupport (4.2.10)
55
i18n (~> 0.7)
66
minitest (~> 5.1)
77
thread_safe (~> 0.3, >= 0.3.4)
@@ -13,79 +13,81 @@ GEM
1313
execjs
1414
coffee-script-source (1.11.1)
1515
colorator (1.1.0)
16-
commonmarker (0.17.10)
16+
commonmarker (0.17.13)
1717
ruby-enum (~> 0.5)
18-
concurrent-ruby (1.0.5)
18+
concurrent-ruby (1.1.3)
19+
dnsruby (1.61.2)
20+
addressable (~> 2.5)
1921
em-websocket (0.5.1)
2022
eventmachine (>= 0.12.9)
2123
http_parser.rb (~> 0.6.0)
2224
ethon (0.11.0)
2325
ffi (>= 1.3.0)
2426
eventmachine (1.2.7)
2527
execjs (2.7.0)
26-
faraday (0.15.2)
28+
faraday (0.15.4)
2729
multipart-post (>= 1.2, < 3)
2830
ffi (1.9.25)
2931
forwardable-extended (2.6.0)
3032
gemoji (3.0.0)
31-
github-pages (177)
32-
activesupport (= 4.2.9)
33-
github-pages-health-check (= 1.3.5)
34-
jekyll (= 3.8.4)
35-
jekyll-avatar (= 0.5.0)
36-
jekyll-coffeescript (= 1.0.2)
33+
github-pages (193)
34+
activesupport (= 4.2.10)
35+
github-pages-health-check (= 1.8.1)
36+
jekyll (= 3.7.4)
37+
jekyll-avatar (= 0.6.0)
38+
jekyll-coffeescript (= 1.1.1)
3739
jekyll-commonmark-ghpages (= 0.1.5)
3840
jekyll-default-layout (= 0.1.4)
39-
jekyll-feed (= 0.9.2)
40-
jekyll-gist (= 1.4.1)
41-
jekyll-github-metadata (= 2.9.3)
42-
jekyll-mentions (= 1.2.0)
41+
jekyll-feed (= 0.11.0)
42+
jekyll-gist (= 1.5.0)
43+
jekyll-github-metadata (= 2.9.4)
44+
jekyll-mentions (= 1.4.1)
4345
jekyll-optional-front-matter (= 0.3.0)
4446
jekyll-paginate (= 1.1.0)
4547
jekyll-readme-index (= 0.2.0)
46-
jekyll-redirect-from (= 0.12.1)
47-
jekyll-relative-links (= 0.5.2)
48-
jekyll-remote-theme (= 0.2.3)
49-
jekyll-sass-converter (= 1.5.0)
50-
jekyll-seo-tag (= 2.3.0)
51-
jekyll-sitemap (= 1.1.1)
48+
jekyll-redirect-from (= 0.14.0)
49+
jekyll-relative-links (= 0.5.3)
50+
jekyll-remote-theme (= 0.3.1)
51+
jekyll-sass-converter (= 1.5.2)
52+
jekyll-seo-tag (= 2.5.0)
53+
jekyll-sitemap (= 1.2.0)
5254
jekyll-swiss (= 0.4.0)
53-
jekyll-theme-architect (= 0.1.0)
54-
jekyll-theme-cayman (= 0.1.0)
55-
jekyll-theme-dinky (= 0.1.0)
56-
jekyll-theme-hacker (= 0.1.0)
57-
jekyll-theme-leap-day (= 0.1.0)
58-
jekyll-theme-merlot (= 0.1.0)
59-
jekyll-theme-midnight (= 0.1.0)
60-
jekyll-theme-minimal (= 0.1.0)
61-
jekyll-theme-modernist (= 0.1.0)
62-
jekyll-theme-primer (= 0.5.2)
63-
jekyll-theme-slate (= 0.1.0)
64-
jekyll-theme-tactile (= 0.1.0)
65-
jekyll-theme-time-machine (= 0.1.0)
66-
jekyll-titles-from-headings (= 0.5.0)
67-
jemoji (= 0.8.1)
68-
kramdown (= 1.16.2)
55+
jekyll-theme-architect (= 0.1.1)
56+
jekyll-theme-cayman (= 0.1.1)
57+
jekyll-theme-dinky (= 0.1.1)
58+
jekyll-theme-hacker (= 0.1.1)
59+
jekyll-theme-leap-day (= 0.1.1)
60+
jekyll-theme-merlot (= 0.1.1)
61+
jekyll-theme-midnight (= 0.1.1)
62+
jekyll-theme-minimal (= 0.1.1)
63+
jekyll-theme-modernist (= 0.1.1)
64+
jekyll-theme-primer (= 0.5.3)
65+
jekyll-theme-slate (= 0.1.1)
66+
jekyll-theme-tactile (= 0.1.1)
67+
jekyll-theme-time-machine (= 0.1.1)
68+
jekyll-titles-from-headings (= 0.5.1)
69+
jemoji (= 0.10.1)
70+
kramdown (= 1.17.0)
6971
liquid (= 4.0.0)
70-
listen (= 3.0.6)
72+
listen (= 3.1.5)
7173
mercenary (~> 0.3)
72-
minima (= 2.1.1)
73-
nokogiri (>= 1.8.1, < 2.0)
74+
minima (= 2.5.0)
75+
nokogiri (>= 1.8.2, < 2.0)
7476
rouge (= 2.2.1)
7577
terminal-table (~> 1.4)
76-
github-pages-health-check (1.3.5)
78+
github-pages-health-check (1.8.1)
7779
addressable (~> 2.3)
78-
net-dns (~> 0.8)
80+
dnsruby (~> 1.60)
7981
octokit (~> 4.0)
8082
public_suffix (~> 2.0)
81-
typhoeus (~> 0.7)
82-
html-pipeline (2.8.4)
83+
typhoeus (~> 1.3)
84+
html-pipeline (2.9.1)
8385
activesupport (>= 2)
8486
nokogiri (>= 1.4)
8587
http_parser.rb (0.6.0)
8688
i18n (0.9.5)
8789
concurrent-ruby (~> 1.0)
88-
jekyll (3.8.4)
90+
jekyll (3.7.4)
8991
addressable (~> 2.4)
9092
colorator (~> 1.0)
9193
em-websocket (~> 0.5)
@@ -98,9 +100,9 @@ GEM
98100
pathutil (~> 0.9)
99101
rouge (>= 1.7, < 4)
100102
safe_yaml (~> 1.0)
101-
jekyll-avatar (0.5.0)
103+
jekyll-avatar (0.6.0)
102104
jekyll (~> 3.0)
103-
jekyll-coffeescript (1.0.2)
105+
jekyll-coffeescript (1.1.1)
104106
coffee-script (~> 2.2)
105107
coffee-script-source (~> 1.11.1)
106108
jekyll-commonmark (1.2.0)
@@ -112,103 +114,102 @@ GEM
112114
rouge (~> 2)
113115
jekyll-default-layout (0.1.4)
114116
jekyll (~> 3.0)
115-
jekyll-feed (0.9.2)
117+
jekyll-feed (0.11.0)
116118
jekyll (~> 3.3)
117-
jekyll-gist (1.4.1)
119+
jekyll-gist (1.5.0)
118120
octokit (~> 4.2)
119-
jekyll-github-metadata (2.9.3)
121+
jekyll-github-metadata (2.9.4)
120122
jekyll (~> 3.1)
121123
octokit (~> 4.0, != 4.4.0)
122-
jekyll-mentions (1.2.0)
123-
activesupport (~> 4.0)
124+
jekyll-mentions (1.4.1)
124125
html-pipeline (~> 2.3)
125126
jekyll (~> 3.0)
126127
jekyll-optional-front-matter (0.3.0)
127128
jekyll (~> 3.0)
128129
jekyll-paginate (1.1.0)
129130
jekyll-readme-index (0.2.0)
130131
jekyll (~> 3.0)
131-
jekyll-redirect-from (0.12.1)
132+
jekyll-redirect-from (0.14.0)
132133
jekyll (~> 3.3)
133-
jekyll-relative-links (0.5.2)
134+
jekyll-relative-links (0.5.3)
134135
jekyll (~> 3.3)
135-
jekyll-remote-theme (0.2.3)
136+
jekyll-remote-theme (0.3.1)
136137
jekyll (~> 3.5)
137-
rubyzip (>= 1.2.2, < 3.0)
138-
typhoeus (>= 0.7, < 2.0)
139-
jekyll-sass-converter (1.5.0)
138+
rubyzip (>= 1.2.1, < 3.0)
139+
jekyll-sass-converter (1.5.2)
140140
sass (~> 3.4)
141-
jekyll-seo-tag (2.3.0)
141+
jekyll-seo-tag (2.5.0)
142142
jekyll (~> 3.3)
143-
jekyll-sitemap (1.1.1)
143+
jekyll-sitemap (1.2.0)
144144
jekyll (~> 3.3)
145145
jekyll-swiss (0.4.0)
146-
jekyll-theme-architect (0.1.0)
146+
jekyll-theme-architect (0.1.1)
147147
jekyll (~> 3.5)
148148
jekyll-seo-tag (~> 2.0)
149-
jekyll-theme-cayman (0.1.0)
149+
jekyll-theme-cayman (0.1.1)
150150
jekyll (~> 3.5)
151151
jekyll-seo-tag (~> 2.0)
152-
jekyll-theme-dinky (0.1.0)
152+
jekyll-theme-dinky (0.1.1)
153153
jekyll (~> 3.5)
154154
jekyll-seo-tag (~> 2.0)
155-
jekyll-theme-hacker (0.1.0)
155+
jekyll-theme-hacker (0.1.1)
156156
jekyll (~> 3.5)
157157
jekyll-seo-tag (~> 2.0)
158-
jekyll-theme-leap-day (0.1.0)
158+
jekyll-theme-leap-day (0.1.1)
159159
jekyll (~> 3.5)
160160
jekyll-seo-tag (~> 2.0)
161-
jekyll-theme-merlot (0.1.0)
161+
jekyll-theme-merlot (0.1.1)
162162
jekyll (~> 3.5)
163163
jekyll-seo-tag (~> 2.0)
164-
jekyll-theme-midnight (0.1.0)
164+
jekyll-theme-midnight (0.1.1)
165165
jekyll (~> 3.5)
166166
jekyll-seo-tag (~> 2.0)
167-
jekyll-theme-minimal (0.1.0)
167+
jekyll-theme-minimal (0.1.1)
168168
jekyll (~> 3.5)
169169
jekyll-seo-tag (~> 2.0)
170-
jekyll-theme-modernist (0.1.0)
170+
jekyll-theme-modernist (0.1.1)
171171
jekyll (~> 3.5)
172172
jekyll-seo-tag (~> 2.0)
173-
jekyll-theme-primer (0.5.2)
173+
jekyll-theme-primer (0.5.3)
174174
jekyll (~> 3.5)
175175
jekyll-github-metadata (~> 2.9)
176-
jekyll-seo-tag (~> 2.2)
177-
jekyll-theme-slate (0.1.0)
176+
jekyll-seo-tag (~> 2.0)
177+
jekyll-theme-slate (0.1.1)
178178
jekyll (~> 3.5)
179179
jekyll-seo-tag (~> 2.0)
180-
jekyll-theme-tactile (0.1.0)
180+
jekyll-theme-tactile (0.1.1)
181181
jekyll (~> 3.5)
182182
jekyll-seo-tag (~> 2.0)
183-
jekyll-theme-time-machine (0.1.0)
183+
jekyll-theme-time-machine (0.1.1)
184184
jekyll (~> 3.5)
185185
jekyll-seo-tag (~> 2.0)
186-
jekyll-titles-from-headings (0.5.0)
186+
jekyll-titles-from-headings (0.5.1)
187187
jekyll (~> 3.3)
188-
jekyll-watch (2.1.1)
188+
jekyll-watch (2.1.2)
189189
listen (~> 3.0)
190-
jemoji (0.8.1)
191-
activesupport (~> 4.0, >= 4.2.9)
190+
jemoji (0.10.1)
192191
gemoji (~> 3.0)
193192
html-pipeline (~> 2.2)
194-
jekyll (>= 3.0)
195-
kramdown (1.16.2)
193+
jekyll (~> 3.0)
194+
kramdown (1.17.0)
196195
liquid (4.0.0)
197-
listen (3.0.6)
198-
rb-fsevent (>= 0.9.3)
199-
rb-inotify (>= 0.9.7)
196+
listen (3.1.5)
197+
rb-fsevent (~> 0.9, >= 0.9.4)
198+
rb-inotify (~> 0.9, >= 0.9.7)
199+
ruby_dep (~> 1.2)
200200
mercenary (0.3.6)
201201
mini_portile2 (2.3.0)
202-
minima (2.1.1)
203-
jekyll (~> 3.3)
202+
minima (2.5.0)
203+
jekyll (~> 3.5)
204+
jekyll-feed (~> 0.9)
205+
jekyll-seo-tag (~> 2.1)
204206
minitest (5.11.3)
205207
multipart-post (2.0.0)
206-
net-dns (0.8.0)
207-
nokogiri (1.8.4)
208+
nokogiri (1.8.5)
208209
mini_portile2 (~> 2.3.0)
209-
octokit (4.9.0)
210+
octokit (4.13.0)
210211
sawyer (~> 0.8.0, >= 0.5.3)
211-
pathutil (0.16.1)
212+
pathutil (0.16.2)
212213
forwardable-extended (~> 2.6)
213214
public_suffix (2.0.5)
214215
rb-fsevent (0.10.3)
@@ -217,9 +218,10 @@ GEM
217218
rouge (2.2.1)
218219
ruby-enum (0.7.2)
219220
i18n
221+
ruby_dep (1.5.0)
220222
rubyzip (1.2.2)
221223
safe_yaml (1.0.4)
222-
sass (3.6.0)
224+
sass (3.7.2)
223225
sass-listen (~> 4.0.0)
224226
sass-listen (4.0.0)
225227
rb-fsevent (~> 0.9, >= 0.9.4)
@@ -230,8 +232,8 @@ GEM
230232
terminal-table (1.8.0)
231233
unicode-display_width (~> 1.1, >= 1.1.1)
232234
thread_safe (0.3.6)
233-
typhoeus (0.8.0)
234-
ethon (>= 0.8.0)
235+
typhoeus (1.3.1)
236+
ethon (>= 0.9.0)
235237
tzinfo (1.2.5)
236238
thread_safe (~> 0.1)
237239
unicode-display_width (1.4.0)
@@ -245,4 +247,4 @@ DEPENDENCIES
245247
jekyll-redirect-from
246248

247249
BUNDLED WITH
248-
1.16.5
250+
1.17.1

_includes/cloudcode/cloud-code.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,41 @@ Parse.Cloud.afterSave("Comment", (request) => {
239239
});
240240
```
241241

242-
The client will receive a successful response to the save request after the handler terminates, regardless of how it terminates. For instance, the client will receive a successful response even if the handler throws an exception. Any errors that occurred while running the handler can be found in the Cloud Code log.
242+
## Async Behavior
243243

244+
In the example above, the client will receive a successful response before the promise in the handler completes, regardless of how the promise resolves. For instance, the client will receive a successful response even if the handler throws an exception. Any errors that occurred while running the handler can be found in the Cloud Code log.
245+
246+
You can use an `afterSave` handler to perform lengthy operations after sending a response back to the client. In order to respond to the client before the `afterSave` handler completes, your handler may not return a promise and your `afterSave` handler may not use async/await.
247+
248+
## Using Request Context
249+
250+
State can be passed from a `beforeSave` handler to an `afterSave` handler in the Reqeuest Context. The following example sends emails to users who are being added to a [Parse.Role's users relation](https://parseplatform.org/Parse-SDK-JS/api/2.1.0/Parse.Role.html#getUsers) asynchronously, so the client receives a response before the emails complete sending:
251+
252+
```javascript
253+
const beforeSave = function beforeSave(request) {
254+
const { object: role } = request;
255+
// Get users that will be added to the users relation.
256+
const usersOp = role.op('users');
257+
if (usersOp && usersOp.relationsToAdd.length > 0) {
258+
// add the users being added to the request context
259+
request.context = { buyers: usersOp.relationsToAdd };
260+
}
261+
};
262+
263+
const afterSave = function afterSave(request) {
264+
const { object: role, context } = request;
265+
if (context && context.buyers) {
266+
const pruchasedItem = getItemFromRole(role);
267+
const promises = context.buyers.map(emailBuyer.bind(null, purchasedItem));
268+
item.increment('orderCount', context.buyers.length);
269+
promises.push(item.save(null, { useMasterKey: true }));
270+
Promise.all(promises).catch(request.log.error.bind(request.log));
271+
}
272+
};
273+
274+
```
275+
276+
## Predefined Classes
244277
If you want to use `afterSave` for a predefined class in the Parse JavaScript SDK (e.g. [Parse.User]({{ site.apis.js }}classes/Parse.User.html)), you should not pass a String for the first argument. Instead, you should pass the class itself.
245278

246279
# beforeDelete Triggers

0 commit comments

Comments
 (0)