书籍地址
https://www.safaribooksonline.com/library/view/developing-nodejs-applications/9780738442853/
1. 创建一个hello world应用
http://bluemix.net/
创建账号并登陆
进入控制台
选择nodejs SDK
创建node应用
使用持续交付工具链
git仓库类型选择new
选择Eclipse Orion Web IDE
编写代码
根/vy102-qqq-nodejs/currentDate/lib/currentDate.js1
2
3exports.currentDateTime = function() {
return Date();
};
根/vy102-qqq-nodejs/currentDate/package.json1
2
3
4{
"name": "currentDate",
"main": "./lib/currentDate"
}
根/vy102-qqq-nodejs/app.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15var http = require("http");
var dateModule = require('./currentDate');
// Read the port from the underlying environment.
// If not exist, use the default port: 8080
var port = process.env.VCAP_APP_PORT || 8080;
// Create the server and listen to requests on the specified port.
http.createServer(function (request, response) {
// Set the content type of the response
response.writeHead(200, {'Content-Type': 'text/plain'});
// Write a simple Hello World message,
// Write a simple Hello World message appended with the current date
response.end('Hello NodeJS! The time now is: ' + dateModule.currentDateTime());
}).listen(port);
根/vy102-qqq-nodejs/package.json1
2
3
4
5
6
7
8{
"name": "NodejsStarterApp",
"version": "0.0.1",
"description": "A Hello World NodeJS sample",
"scripts": {
"start": "node app.js"
}
}
根/vy102-qqq-nodejs/manifest.yml1
2
3
4
5
6
7
8applications:
- path: .
memory: 256M
instances: 1
domain: au-syd.mybluemix.net
name: vy102-qqq-nodejs
host: vy102-qqq-nodejs
disk_quota: 1024M
创建配置项
运行项目
2. Understanding asynchronous callback
Watson Language Translator
https://language-translator-demo.ng.bluemix.net/
与nodejs sdk操作相同,在控制台搜索language translator并添加。
orion编译器里,编辑启动配置,绑定服务
app.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/*eslint-disable no-unused-params */
var http = require("http");
const translatorModule = require('./translator');
var helloText = 'Hello';
var fromLanguage = 'en';
var toLanguage = 'es';
var portNumber = process.env.VCAP_APP_PORT || 8080;
const server = http.createServer(handleRequests);
server.listen(portNumber, function () {
console.log('Server is up!');
});
function handleRequests(userRequest, userResponse) {
userResponse.writeHead(200, {
'Content-Type': 'text/plain'
});
var callback = function (error, translatorOutput) {
if (error) {
userResponse.end(error);
} else {
userResponse.end('Translation of ' + helloText + " is " + translatorOutput);
}
};
translatorModule.getTranslation(helloText, fromLanguage, toLanguage, callback);
}
translator/lib/translator.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30//const watson = require('watson-developer-cloud');
var LanguageTranslatorV3 = require('watson-developer-cloud/language-translator/v3');
exports.getTranslation = function getTranslation(helloText, fromLanguage, toLanguage, callback) {
var language_translator = new LanguageTranslatorV3({
version: '2018-05-01',
iam_apikey: 'zODif6DVPCj-sQOlydcaq4Wqfx3cVr_oTjZjznplbpXi',
url: 'https://gateway-syd.watsonplatform.net/language-translator/api'
});
var translatorCallback = function (err, data) {
if (err) {
console.log(err);
callback(err, null);
} else {
console.log(data);
callback(null, data.translations[0].translation);
}
};
language_translator.translate({
text: helloText,
source: fromLanguage,
target: toLanguage
}, translatorCallback);
};
3. Creating your first Express application
https://github.com/ibm-redbooks-dev/vy102-XXX-express
Watson Natural Language Understanding service
https://console.bluemix.net/apidocs/natural-language-understanding?language=node
package.json1
2
3
4
5
6
7
8
9
10{
"name": "vy102-qqq-nodejs",
"version": "0.0.1",
"description": "A sample express app",
"dependencies": {
"express": "4.16.4",
"body-parser": "1.18.3",
"watson-developer-cloud": "3.13.0"
}
}
app.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24var port = process.env.VCAP_APP_PORT || 8080;
//Express Web Framework, and create a new express server
var express = require('express'),
app = express();
var bodyParser = require('body-parser');
//Routes modules
var index = require('./routes'),
author = require('./routes/author');
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
extended: false
}));
//In case the caller access any URI under the root /, call index route
app.use('/', index);
//In case the caller access any URI under /author, call author route
app.use('/author', author);
// start server on the specified port and binding host
app.listen(port);
views/index.html1
2
3
4
5
6
7
8
9
10
11
12<html>
<body>
<h1 style="color:blue;">Watson Author Finder</h1>
<p>To get information about the author of an article, enter the URL of that article.</p>
<form action="author" method="post">
<input type="text" name="url" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
services/articleServices.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40// Watson Natural Language Understanding third party module
//Specify the release for the Natural Language Understanding service
var NaturalLanguageUnderstandingV1 = require('watson-developer-cloud/natural-language-understanding/v1.js');
var natural_language_understanding = new NaturalLanguageUnderstandingV1({
'version_date': NaturalLanguageUnderstandingV1.VERSION_DATE_2017_02_27,
iam_apikey: 'hySqyRqhRmlCaUeMlxF8Sk29T8ovIGzkFYOfVZH33oPQ',
url: 'https://gateway-syd.watsonplatform.net/natural-language-understanding/api'
});
//error message for missing URL
const MISSING_URL_ERROR = 'URL not passed';
exports.extractArticleAuthorNames = function (req, callback) {
//If the url is not passed, return error to the caller
if (req === null || req.body === null || req.body.url === null) {
callback(MISSING_URL_ERROR, null);
return;
}
// url is the parameter passed in the POST request to /author
// It contains the URL of the article
// The metadata feature returns the author, title, and publication date.
var parameters = {
'url': req.body.url,
'features': {
'metadata': {}
}
};
// Call the Watson service and return the list of authors
natural_language_understanding.analyze(parameters, function (err, response) {
if (err)
callback(err, null);
else
callback(null, response.metadata.authors);
});
};
routes/index.js1
2
3
4
5
6
7
8
9
10
11
12
13// index.js - Index route module
var express = require('express');
var router = express.Router();
//Provides utilities for dealing with directories
var path = require('path');
// Home page route
router.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '../views/index.html'));
});
module.exports = router;
routes/author.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// author.js - Author route module
var express = require('express');
var router = express.Router();
var articleServices = require('../services/articleServices');
router.post('/', function (req, res) {
articleServices.extractArticleAuthorNames(req, function (err, response) {
if (err)
res.status(500).send('error: ' + err);
else
res.send(response);
});
});
module.exports = router;
4. Building a rich front-end application by using React and ES6
react不太了解,先放代码,以后再学习
代码格式化,勾选Support e4x/jsx syntax
https://beautifier.io/
frontend/components/components.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
url: '',
authors: [],
inputVal: ''
};
}
updateUrl(e) {
this.setState({
inputVal: e.target.value
});
}
// getAuthor uses the fetch function to retrieve authors
// from the REST service created in the previous exercise
getAuthor() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
fetch('/author', {
method: 'POST',
body: "url=" + this.state.inputVal,
headers: myHeaders
}).then(res => res.json())
.then(data => this.setState({
authors: data,
url: this.state.inputVal
}));
}
// Render is the core function behind React components.
// It defines components and elements in XML format.
// This is only feasible if using JSPX and Babel JavaScript compiler.
render() {
return (
<div class="jumbotron text-center">
<h1>Author Finder</h1>
<div id='input-form' class='text-center'>
<input type="text" class="form-control input-lg text-center" onChange={e=>this.updateUrl(e)} placeholder="Enter URL of Article here!"/>
</div>
<br/>
<button type="button" class="btn btn-primary btn-lg" disabled = {this.state.inputVal.length===0} onClick={()=>{this.getAuthor()}}>Retrieve Author</button>
<Results url={this.state.url} hide={this.state.authors.length === 0} authors={this.state.authors}/>
</div>
)
}
}
// Results: is another React component
// It creates the list of AuthorRecords
class Results extends React.Component {
constructor(props) {
super(props);
}
render() {
if (this.props.hide) {
return null;
}
return (
<div class='form-inline'>
<div class="row">
<div class="col-xs-12 col-md-3">
<h2>Article URL:</h2>
</div>
<div class="col-xs-12 col-md-9">
{this.props.url}
</div>
</div>
<div class="row">
<div class="col-xs-12 col-md-3">
<h2>Authors:</h2>
</div>
<div class="col-xs-12 col-md-9">
<div class="row">
{this.renderAuthors()}
</div>
</div>
</div>
</div>
)
}
/*
Notice the AuthorRecord is defined in a separate file. This is a powerful feature of the React Component: Putting the AuthorRecord in a separate file and making it a reusable component.
*/
renderAuthors() {
/* When developing a component, you should capitalize it.
Hence, you should use "AuthorRecord" instead of "authorrecord" in order to identify it as a component to React.
*/
let authors = this.props.authors;
return authors.map(a => {
return <AuthorRecord author = {a}/>;
});
}
}
ReactDOM.render(<Container />, document.getElementById("root"));
frontend/components/authorrecords.js1
2
3
4
5
6
7
8
9
10
11
12
13// AuthorRecord : a component defined to hold author names
class AuthorRecord extends React.Component {
render() {
return (
<div class="row">
<div class="col-xs-12 col-md-6">
{this.props.author.name}
</div>
</div>
);
}
}
frontend/index.html1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35<html>
<head>
<title>React JS - Author Finder</title>
</head>
<body>
<!-- Loading the script in body is a recommendation to ensure faster loading,
putting all scripts at the header will cause the page to wait till all scripts loaded
Load React related files from internet -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<!-- Load babel JavaScript compiler from internet -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script type="text/babel" src="./components/authorrecords.js"></script>
<script type="text/babel" src="./components/components.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
<div class="container">
<div class="row">
<!-- You do not need to write much html code, you will
build the whole html on your JSPX code -->
<div class="col-sm-10 col-sm-offset-1 text-center" id="root">
</div>
</div>
</div>
</body>
</html>
app.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25var port = process.env.VCAP_APP_PORT || 8080;
//Express Web Framework, and create a new express server
var express = require('express'),
app = express();
var bodyParser = require('body-parser');
//Routes modules
var author = require('./routes/author');
//Serve the files in /frontend as static files
app.use(express.static(__dirname + '/frontend'));
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
extended: false
}));
//In case the caller access any URI under /author, call author route
app.use('/author', author);
// start server on the specified port and binding host
app.listen(port);