From Event to Action: Accelerate Your Decision Making with Real-Time Automation
Parse cloud code
1. Parse Cloud Code
Building Web Apps WITH Programming Server a little bit.
http://goo.gl/oW1cZD
2014 Spring Web Programming, NCCU
Author: pa4373 (Licensed by CC-By 4.0)
6. To work with Cloud Code, you shall understand
how Parse actually works.
7. RESTful API
● RESTful API is the design principle of Web
Service
● Web Service: content consumable for
computer program. (Developers love it!)
8. RESTful API
How web service client works:
1. Construct HTTP request
2. Get HTTP response
3. Parse HTTP response (plain text) into native
data types supported by your programming
language.
4. Do whatever you like.
Programming language independent.
9. RESTful API
{
"resultCount":1,
"results": [
{"wrapperType":"artist", "artistType":"Artist",
"artistName":"Jack Johnson", "artistLinkUrl":"https:
//itunes.apple.com/us/artist/jack-johnson/id909253?
uo=4", "artistId":909253, "amgArtistId":468749,
"primaryGenreName":"Rock", "primaryGenreId":21,
"radioStationUrl":"https://itunes.apple.
com/station/idra.909253"}]
}
var object = JSON.parse(res);
// Do something with object variable.
plain text
10. RESTful API
Q: How client & server talks to each other?
● protocol, standard
○ SOAP (Simple Object Access Protocol)
○ XML RPC
○ REST
13. RESTful API: REST
REST: Representational State Transfer
What is that?
The story begins with the invention of HTTP by
Sir Tim-Berners Lee.
CERN, Swiss, 1990
14. RESTful API: REST
● WEB is a place providing resources.
● the very first version of HTTP:
○ GET
● HTTP 1.0
○ GET, POST and HEAD
● HTTP 1.1
○ GET, POST, HEAD, OPTIONS, PUT, DELETE,
PATCH
15. RESTful API: Resources
A resource is an object with a type, associated
data, relationships to other resources,
http://restful-api-design.readthedocs.org/en/latest/scope.html
17. How Parse Works
Your Code
Parse SDK (黑箱)
產生HTTP請求 產生HTTP回應
Parse Cloud (RESTful API)
18. Cloud Code
Bring server programming back to Parse while
not entirely dealing with server logic, Awesome!
docs: https://parse.com/docs/cloud_code_guide
19. Cloud Code
All source code available on GitHub:
$ git clone https://github.com/pa4373/wp2014s_cloudcode_example.git
20. Use Cloud Code
Install command-line tool:
● OS X / Linux
○
○ python, curl is required. ( usually included in OS. )
● Windows
○ https://parse.com/downloads/windows/console/parse.zip
$ curl -s https://www.parse.com/downloads/cloud_code/installer.sh | sudo /bin/bash
21. Use Cloud Code
Setting up Cloud Code
# Create new cloud code folder containing basic files
$ parse new cloudcode_demo
Email: pa4373@gmail.com
Password: # You won’t see **** while typing, stop asking!
1: ParseStore
2: PeerEvaluation
3: cloudcode_demo
Select an App: 3
# You shall see all apps on Parse, select one to link with
$ cd cloudcode_demo # change into the folder newly created
22. Use Cloud Code
Q: What’s my password?
A: If you use Facebook, Google, GitHub to
login,
you might need to go to “Account” to manually
set your password.
23. Use Cloud Code
Basic folder structure
# let’s see what parse cloud deploy created for us
.
├── cloud
│ └── main.js
# This is where cloud code are stored.
├── config
│ └── global.json
# A JSON file telling Parse how to deploy your code,
# normally you don’t need to worry about it.
└── public
└── index.html
# Few static files you want Parse to host.
24. Use Cloud Code
Write the very first cloud code function:
Open main.js and add the following codes.
Parse.Cloud.define("hello", function(request, response) {
response.success("Hello world!");
// You need to include response.success/error in Cloud
Code indicating the end of the request, or the codes will
went wrong.
});
25. Use Cloud Code
Deploy to the cloud:
in the project directory, typing:
$ parse deploy
Uploading source files
Finished uploading files
New release is named v2 (using Parse JavaScript SDK v1.
2.18)
26. Use Cloud Code
Call the function we just wrote. (Client JS)
Parse.Cloud.run('hello', {}, {
success: function(result) {
window.alert(result);
// result is 'Hello world!'
},
error: function(error) {
}
});
28. Use Cloud Code
Cloud Code Dashboard
Files: Cloud Code (Live editing)
Logs: console.log (Great for debugging)
Scheduled Jobs: See queued jobs
Job Status: See job status
29. Use Cloud Code
Topic Covered Today:
● beforeSave, afterSave, beforeDelete, and
afterDelete
● Parse.Cloud.httpRequest
● Background Jobs
● Modules
● Settings for Development vs. Production
30. Use Cloud Code
beforeSave, afterSave, beforeDelete, and
afterDelete:
Act as a hook, allow developers to perform
some operations before CRUD.
31. Use Cloud Code
Change its value before the object is saved
on Parse.
Parse.Cloud.beforeSave("ExampleClass", function(request,
response) {
request.object.set("text", "Always the same.");
response.success();
});
32. Use Cloud Code
Save an object to Parse and retrieve its value.
(Client JS)
var ExampleClass = Parse.Object.extend("ExampleClass");
var example_object = new ExampleClass();
example_object.set('text', 'I don't believe it!');
example_object.save(null, {
success: function(object){
var text = object.get('text');
window.alert(text);
}, error: function(object){
}
});
35. Use Cloud Code
API in the example: iTunes API
Documentation: https://www.apple.
com/itunes/affiliates/resources/documentation/it
unes-store-web-service-search-api.html
API to use:
https://itunes.apple.com/search?
term=john+mayer
36. Use Cloud Code
https://itunes.apple.com/search?term=john+mayer
Parse.Cloud.httpRequest({
url: 'https://itunes.apple.com/search',
params: {
term: request.params.singer // request.params as the Query Object
},
success: function (httpResponse) {
var SongClass = Parse.Object.extend('SongClass');
var ResObj = JSON.parse(httpResponse.text);
var newlyCreatedObjList = ResObj.results.map(function (e) {
var object = new SongClass();
object.set('trackName', e['trackName']);
return object;
});
// Resolve multiple asynchronous save problem (When to send http response?)
Parse.Object.saveAll(newlyCreatedObjList, {
success: function (list) {
response.success(request.params.singer + " is awesome!");
},
error: {}
});
},
error: function (httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
}
});
37. Use Cloud Code
Let’s put it into our ‘Hello World’ cloud code
app!
Parse.Cloud.define("get", function(request, response) {
// Put codes shown on the last page here.
});
38. Use Cloud Code
Call the function we just wrote. (Client JS)
Parse.Cloud.run('get', {singer: 'John Mayer'}, {
success: function(result) {
window.alert(result);
// result is 'John Mayer is awesome'
},
error: function(error) {
}
});
42. Use Cloud Code
Background Jobs:
Let’s say: we want to run the codes on previous
example per hour, periodically.
43. Use Cloud Code
Background Jobs:
Define the jobs
Parse.Cloud.job("iTunesAPI", function(request, status) {
// Put the codes in the previous example here.
});
44. Use Cloud Code
Background Jobs:
Parse.Cloud.job("iTunesAPI", function(request, status) {
Parse.Cloud.httpRequest({
url: 'https://itunes.apple.com/search',
params: {
term: request.params.singer
},
success: function (httpResponse) {
var SongClass = Parse.Object.extend('SongClass');
var ResObj = JSON.parse(httpResponse.text);
var newlyCreatedObjList = ResObj.results.map(function(e){
var object = new SongClass();
object.set('trackName', e['trackName']);
return object;
});
Parse.Object.saveAll(newlyCreatedObjList, {
success: function(list){
status.success(request.params.singer+" is awesome!"); // status required for a function to
stop.
}, error: {}
});
},
error: function (httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
}
});
});
49. Use Cloud Code
Advanced: Write a web crawler using
Background Jobs, httpRequest
Programmers love API and web service.
The regular users don’t.
How to extract information from normal web
page?
53. Use Cloud Code
Parse doesn’t support modules written in C /
C++, exposed from JavaScript.
No magical package manager (i.e npm, to use).
TAT
Grab native javascript modules to cloud folder
and put var module = require('cloud/<module filename>'); in
your code.
54. Use Cloud Code
Grab https://github.com/isaacs/sax-js/blob/master/lib/sax.js
as sax.js in cloud folder.
Grab https://github.com/SamDecrock/node-
xmlreader/blob/master/xmlreader.js as xmlreader.js in
cloud folder.
Replace
var sax = require("sax"); with var sax = require("cloud/sax.js");
var saxparser = sax.parser(true); with var saxparser = sax.parser(false);
in xmlreader.js
https://parse.com/questions/htmlxml-parser-with-
xpath-on-cloud-code
55. Use Cloud Code
XPath: a way to describe element in a DOM tree,
ex: /html/body/div[3]/div/ul/li/div[2]/p[2]
a little bit like CSS selector
Using ‘inspect element’ to look up Xpath.
58. Use Cloud Code
Parse.Cloud.job("webpage_scraping", function(request, status) {
var xmlreader = require('cloud/xmlreader.js');
Parse.Cloud.httpRequest({
url: 'http://www.ericclapton.com/tour',
success: function (httpResponse) {
xmlreader.read(httpResponse.text, function(err, doc){
var arena = doc.HTML.BODY.DIV.at(1).DIV.at(0).DIV.at(2).DIV.at(0).DIV.at(2).
DIV.at(0).DIV.at(0).TABLE.at(0).TBODY.at(0).TR.at(1).TD.at(1).A.at(0).text();
///html/body/div[2]/div/div[3]/div/div[3]/div/div/table/tbody/tr[2]/td[2]/a
var ConcertArenaClass = Parse.Object.extend('ConcertArenaClass');
var obj = new ConcertArenaClass();
obj.set('arena', arena);
obj.save(null, {
success: function(obj){
status.success('arena saved.');
}, error: {}
});
});
},
error: function (httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
}
});
});
59. Use Cloud Code
var xmlreader = require('cloud/xmlreader.js');
xmlreader.read(httpResponse.text, function(err, doc){
var arena = doc.HTML.BODY.DIV.at(1).DIV.at(0).DIV.at(2).DIV.at(0).DIV.at(2).
DIV.at(0).DIV.at(0).TABLE.at(0).TBODY.at(0).TR.at(1).TD.at(1).A.at(0).text();
// XPath: /html/body/div[2]/div/div[3]/div/div[3]/div/div/table/tbody/tr[2]/td[2]/a
// Watch the index diffirence. (start from 0, start from 1 -> None)
});
61. Use Cloud Code
Technique: Hack AJAX page
Some web page content is powered by AJAX technique, use ‘Inspect Elemenet’
62. Use Cloud Code
Always try to find API before writing your
own crawler!
Be practical.
63. Use Cloud Code
Modules
Imagine you got the codes from your peer, with
10k+ LoC in there.
Are you ready to debug to die?
Or say, write every function by your own.
And you wishes you were dead.
64. Use Cloud Code
Modules
● Write your own module
● Cloud modules
● Use Third-party modules (Painful!)
65. Use Cloud Code
Modules
● Write your own module
var coolNames = ['Ralph', 'Skippy', 'Chip', 'Ned', 'Scooter'];
exports.isACoolName = function(name) {
return coolNames.indexOf(name) !== -1;
}
var name = require('cloud/name.js');
name.isACoolName('Fred'); // returns false
name.isACoolName('Skippy'); // returns true;
name.coolNames; // undefined.
cloud/name.js
cloud/main.js
There’s a global exports object.
66. Use Cloud Code
Modules
● Write your own module
● Cloud modules
○ https://www.parse.com/docs/cloud_modules_guide
● Use Third-party modules
○ Put pure js modules in your cloud directory, and use
‘var mod = require('cloud/name.js');’
67. Use Cloud Code
Settings for Development vs. Production
You got a app running for production,
but you also want to add some cool features,
what to do now?
Modify Production on the fly, dangerous and
stupid!
69. Use Cloud Code
Settings for Development vs. Production
Production App
Development App
Your Cloud Code
Project
70. Use Cloud Code
Settings for Development vs. Production
Link other apps to your project
# Link existing project to other apps, accessible via
alias ‘production’
$ parse add production
Email: pa4373@gmail.com
Password: # You won’t see **** while typing, stop asking!
1: ParseStore
2: PeerEvaluation
3: cloudcode_demo
4: cloudcode_demo_production
Select an App: 4
71. Use Cloud Code
Settings for Development vs. Production
Developing Cloud Code
# Deploy tool will monitor files change on fly and updated
to Parse server (No more deploy again)
$ parse develop <APP_NAME>
E2013-03-19:20:17:01.423Z] beforeSave handler in release
'v1' ran for GameScore with the input:
{"original": null, "update":{"score": 1337}}
and failed validation with Each GamesScore must have a
playerName
New release is named v58
I2013-03-19T20:17:10.343Z] Deployed v58 with triggers:
GameScore:
before_save
72. Use Cloud Code
Settings for Development vs. Production
Deploy Code to Production
$ parse deploy production
New release is named v2