package.json
{
"version": "1.0.0"
, "name": "react-redux"
, "description": "React Redux"
, "engines": {
"node": "6.3.1"
, "npm": "3.10.6"
}
, "dependencies": {
"webpack": "*"
, "webpack-dev-server": "*"
, "babel-core": "*"
, "babel-preset-es2015": "*"
, "babel-preset-react": "*"
, "babel-loader": "*"
, "react": "*"
, "react-dom": "*"
, "redux": "*"
}
, "scripts": {
"build": "node node_modules/webpack-dev-server/bin/webpack-dev-server --progress"
}
}
webpack.config.js
var path = require('path');
module.exports = {
entry: [path.resolve(__dirname + '/source/app.jsx')]
, output: {
path: path.resolve(__dirname)
, filename: 'app.js'
}
, module: {
loaders: [
{
test: /\.jsx?$/
, exclude: /node_modules/
, loader: 'babel-loader'
, query: {
presets: ['es2015', 'react']
}
}
]
}
};
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://fb.me/react-0.14.3.js"></script>
<script src="https://fb.me/react-dom-0.14.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.min.js"></script>
<title>Redux React Counter</title>
</head>
<body>
<div id="root"></div>
<script src="app.js"></script>
</body>
</html>
source/app.jsx
const {createStore} = Redux;
// Reducer
const counter = (state = 0, action) => {
switch(action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
// Store
const store = createStore(counter);
// Subscribe
store.subscribe(render);
// Dispatch
const render = () => {
ReactDOM.render(
<Counter value={store.getState()}
onIncrement={() => store.dispatch({type: 'INCREMENT'})}
onDecrement={() => store.dispatch({type: 'DECREMENT'})}
/>, document.getElementById('root')
);
};
class Counter extends React.Component {
render() {
return (
<div>
<h1>{this.props.value}</h1>
<button onClick={this.props.onIncrement}>+</button>
<button onClick={this.props.onDecrement}>-</button>
</div>
);
}
};
render();
вторник, 9 августа 2016 г.
среда, 3 августа 2016 г.
Redux Cheat Sheet
Stores
import { createStore } from 'redux';
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT':return state - 1;
default: return state;
}
}
let store = createStore(counter);
store.subscribe(() => { ... })
store.dispatch({ action })
store.getState()
store.dispatch({ type: 'INCREMENT' }); // 1
store.dispatch({ type: 'DECREMENT' }); // 10
React Redux
React.render(<Provider store={store}>{() => <App />}</Provider>, mountNode)
class App extends React.Component {
render () { return <div>{this.props.message}</div> }
}
function select (state) {
return { message: state.message }
}
export default connect(select)(App);
import { createStore } from 'redux';
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT':return state - 1;
default: return state;
}
}
let store = createStore(counter);
store.subscribe(() => { ... })
store.dispatch({ action })
store.getState()
store.dispatch({ type: 'INCREMENT' }); // 1
store.dispatch({ type: 'DECREMENT' }); // 10
React Redux
React.render(<Provider store={store}>{() => <App />}</Provider>, mountNode)
class App extends React.Component {
render () { return <div>{this.props.message}</div> }
}
function select (state) {
return { message: state.message }
}
export default connect(select)(App);
React Cheat Sheet
Основы
1. React.createElement(type, props, children)
Создать ReactElement с переданными ему class, props, children.
var link = React.createElement('a', {href: '#'}, "Save")
var nav = React.createElement(MyNav, {flat: true}, link)
2. React.cloneElement(element, props, children)
Создать новый ReactElement объединенный с новыми props и children.
3. ReactDOM.render(element, domNode)
Взять ReactElement, отредерить его и вставить DOM node.
ReactDOM.render(React.createElement('div'), document.getElementById('container'))
4. ReactDOM.findDOMNode(element)
Вернуть DOM node соответствующий заданному элементу (после рендеринга).
Особые props
children - автоматически добавляется в this.props функцикй React.createElement.
className - соответствует атрибуту class в HTML.
htmlFor - соответствует атрибуту for в HTML.
key - уникальные идентификаторы для каждого ReactElement. Используется с элементами в массивах.
ref - принимает callback function, которая будет вызвана:
1. с экземпляром компонента или DOM node при его монтировании (mount).
2. с null или unmount и когда произошло изменение функционала.
style - принимает объект со стилями style вместо строки.
Типы props
Доступны в составе React.PropTypes. По желанию добавить .isRequired.
| any | array | bool | element | func |
| node | number | object | string |
instanceOf(constructor)
oneOf(['News', 'Photos'])
oneOfType([propType, propType])
Компоненты Class Components
var MyComponent = React.createClass({
displayName: 'MyComponent',
/* ... options and lifecycle methods ... */
render: function() {
return React.createElement( /* ... */ )
},
... далее опции и методы ...
});
Опции
propTypes - объект содержащий сопоставления имен props с их типами
getDefaultProps - function() возвращает объект
getInitialState - function() возвращает объект
Методы жизненного цикла компоненты
componentWillMount - function()
componentDidMount - function()
componentWillReceiveProps - function(nextProps)
shouldComponentUpdate - function(nextProps, nextState) возвращает boolen
componentWillUpdate - function(nextProps, nextState)
componentDidUpdate - function(prevProps, prevState)
componentWillUnmount - function()
Описание характеристик экземпляров компонентов:
- Доступны через this внутри класса компонента (class component)
- Компоненты без состояний (stateless functional components) не имеют экземпляров компонентов (component instances).
- Обслуживаются как объекты переданные в ref callbacks
- Один экземпляр компонента может обслуживать множество ReactElements.
Свойства
props - содержит любые свойства props переданные в React.createElement
state - содержит состояние state установленное через функцию setState и полученное через функцию getInitialState
Методы
1. setState(changes) - применяет изменения к this.state и перерисовывает компонент
2. forceUpdate() - немендленно перерисовывает компонент в DOM
Код в стиле ECMAScript 6
Компоненты - это классы
export class MyComponent extends Component {
componentWillMount() {
// ...
}
render() {
return <div>Hello World</div>
}
}
Свойства статичны
export class MyComponent extends Component {
static propTypes = {
// ...
}
static defaultProps = {
// ...
}
}
Первоначальное состояние
export class MyComponent extends Component {
state = {
disabled: this.props.disabled,
}
}
Конструкторы заменяют собой componentWillMount
export class MyComponent extends Component {
constructor(props) {
super(props)
// Do stuff
}
}
Привязывайте методы к вашему компоненту, когда используете их в качестве обработчиков handlers
export class MyComponent extends Component {
onMouseEnter = event => {
this.setState({hovering: true})
}
}
Импорт React
JSX предполагает, что объект React доступен, поэтому его надо тоже импортировать
import React, { Component, PropTypes } from 'react'
Деструктурирование особенно удобно для компонентов с неизменным состоянием (stateless)
export const Commas = ({items, ...otherProps}) => <div {...otherProps}>{items.join(', ')}</div>
Строковые литералы можно использовать для динамического создания className
<input className={`Control-${this.state}`} />
и для создания динамических имен свойств
this.setState({
[`${inputName}Value`]: e.target.value,
});
Декораторы классов можно использовать в качестве mixin
@something(options)
class MyComponent extends Component {}
// В итоге превращается в
let MyComponent = something(options)(
class MyComponent extends Components {}
)
Дополнительные подсказки
Basic class
React.createClass({
render: function () {
return (
<div>Hello {this.props.name}</div>
);
}
});
Using components
var Component = React.createClass({ ... });
var compo = React.render(<Component />, mountnode);
States
this.setState({ editing: true });
this.state.editing === true
this.replaceState({ ... });
Properties
this.setProps({ fullscreen: true });
this.props.fullscreen === true
this.replaceProps({ ... });
API
c.getDOMNode() // deprecated 0.13
React.findDOMNode(c) // 0.13+
c.forceUpdate()
c.isMounted()
Methods
{
render: function()
getInitialState: function()
getDefaultProps: function()
mixins: []
propTypes: {} / for validation /
statics: { .. } / static methods /
displayName: '..' / automatically filled in by jsx /
}
Lifecycle
componentWillMount()
componentDidMount()
// not on initial render
componentWillReceiveProps(props)
shouldComponentUpdate(props, state)
componentWillUpdate(props, state)
componentDidUpdate(prevProps, prevState)
componentWillUnmount()
// ...there is no DidUnmount or ReceiveState.
Initial States
React.createClass({
getInitialState: function () {
return {data: []};
},
render: function () {
return (
<CommentList data={this.state.data} />
);
}
});
Default Properties
React.createClass({
getDefaultProps: function () {
return {name: ''};
}
);
Before Rendering
React.createClass({
componentWillMount: function () {
$.get(this.props.url, function (data) {
this.setState(data);
});
},
render: function () {
return (
<CommentList data={this.state.data} />
);
}
});
Actions
<form onSubmit={this.handleSubmit}>
Name: <input ref="name">
</form>
React.createClass({
handleSubmit: function (event) {
name = this.refs['name'].getDOMNode().value;
// see two-way binding below
}
})
Two-way binding
React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {value: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('value')} />;
}
});
// LinkedStateMixin adds a method to your React component called
// linkState().
Lists
var TodoList = React.createClass({
render: function() {
var createItem = function(itemText) {
return <li>{itemText}</li>;
};
return <ul>{this.props.items.map(createItem)}</ul>;
}
});
Property validations
React.createClass({
propTypes: {
// required
requiredFunc: React.PropTypes.func.isRequired,
requiredAny: React.PropTypes.any.isRequired,
// primitives, optional by default
bool: React.PropTypes.bool,
func: React.PropTypes.func,
number: React.PropTypes.number,
string: React.PropTypes.string,
}
});
Class set
render: function() {
var cx = React.addons.classSet;
var classes = cx({
'message': true,
'message-important': this.props.isImportant,
'message-read': this.props.isRead
});
// same final string, but much cleaner
return <div className={classes}>Great Scott!</div>;
}
Propagating properties to children
var VideoPlayer = React.createClass({
render: function() {
return <VideoEmbed {...this.props} controls='false' />;
}
});
<VideoPlayer src="video.mp4" />
Mixins
var TickTock = React.createClass({
mixins: [SetIntervalMixin]
}
SetIntervalMixin = {
componentWillMount: function() { .. }
}
1. React.createElement(type, props, children)
Создать ReactElement с переданными ему class, props, children.
var link = React.createElement('a', {href: '#'}, "Save")
var nav = React.createElement(MyNav, {flat: true}, link)
2. React.cloneElement(element, props, children)
Создать новый ReactElement объединенный с новыми props и children.
3. ReactDOM.render(element, domNode)
Взять ReactElement, отредерить его и вставить DOM node.
ReactDOM.render(React.createElement('div'), document.getElementById('container'))
4. ReactDOM.findDOMNode(element)
Вернуть DOM node соответствующий заданному элементу (после рендеринга).
Особые props
children - автоматически добавляется в this.props функцикй React.createElement.
className - соответствует атрибуту class в HTML.
htmlFor - соответствует атрибуту for в HTML.
key - уникальные идентификаторы для каждого ReactElement. Используется с элементами в массивах.
ref - принимает callback function, которая будет вызвана:
1. с экземпляром компонента или DOM node при его монтировании (mount).
2. с null или unmount и когда произошло изменение функционала.
style - принимает объект со стилями style вместо строки.
Типы props
Доступны в составе React.PropTypes. По желанию добавить .isRequired.
| any | array | bool | element | func |
| node | number | object | string |
instanceOf(constructor)
oneOf(['News', 'Photos'])
oneOfType([propType, propType])
Компоненты Class Components
var MyComponent = React.createClass({
displayName: 'MyComponent',
/* ... options and lifecycle methods ... */
render: function() {
return React.createElement( /* ... */ )
},
... далее опции и методы ...
});
Опции
propTypes - объект содержащий сопоставления имен props с их типами
getDefaultProps - function() возвращает объект
getInitialState - function() возвращает объект
Методы жизненного цикла компоненты
componentWillMount - function()
componentDidMount - function()
componentWillReceiveProps - function(nextProps)
shouldComponentUpdate - function(nextProps, nextState) возвращает boolen
componentWillUpdate - function(nextProps, nextState)
componentDidUpdate - function(prevProps, prevState)
componentWillUnmount - function()
Описание характеристик экземпляров компонентов:
- Доступны через this внутри класса компонента (class component)
- Компоненты без состояний (stateless functional components) не имеют экземпляров компонентов (component instances).
- Обслуживаются как объекты переданные в ref callbacks
- Один экземпляр компонента может обслуживать множество ReactElements.
Свойства
props - содержит любые свойства props переданные в React.createElement
state - содержит состояние state установленное через функцию setState и полученное через функцию getInitialState
Методы
1. setState(changes) - применяет изменения к this.state и перерисовывает компонент
2. forceUpdate() - немендленно перерисовывает компонент в DOM
Код в стиле ECMAScript 6
Компоненты - это классы
export class MyComponent extends Component {
componentWillMount() {
// ...
}
render() {
return <div>Hello World</div>
}
}
Свойства статичны
export class MyComponent extends Component {
static propTypes = {
// ...
}
static defaultProps = {
// ...
}
}
Первоначальное состояние
export class MyComponent extends Component {
state = {
disabled: this.props.disabled,
}
}
Конструкторы заменяют собой componentWillMount
export class MyComponent extends Component {
constructor(props) {
super(props)
// Do stuff
}
}
Привязывайте методы к вашему компоненту, когда используете их в качестве обработчиков handlers
export class MyComponent extends Component {
onMouseEnter = event => {
this.setState({hovering: true})
}
}
Импорт React
JSX предполагает, что объект React доступен, поэтому его надо тоже импортировать
import React, { Component, PropTypes } from 'react'
Деструктурирование особенно удобно для компонентов с неизменным состоянием (stateless)
export const Commas = ({items, ...otherProps}) => <div {...otherProps}>{items.join(', ')}</div>
Строковые литералы можно использовать для динамического создания className
<input className={`Control-${this.state}`} />
и для создания динамических имен свойств
this.setState({
[`${inputName}Value`]: e.target.value,
});
Декораторы классов можно использовать в качестве mixin
@something(options)
class MyComponent extends Component {}
// В итоге превращается в
let MyComponent = something(options)(
class MyComponent extends Components {}
)
Дополнительные подсказки
Basic class
React.createClass({
render: function () {
return (
<div>Hello {this.props.name}</div>
);
}
});
Using components
var Component = React.createClass({ ... });
var compo = React.render(<Component />, mountnode);
States
this.setState({ editing: true });
this.state.editing === true
this.replaceState({ ... });
Properties
this.setProps({ fullscreen: true });
this.props.fullscreen === true
this.replaceProps({ ... });
API
c.getDOMNode() // deprecated 0.13
React.findDOMNode(c) // 0.13+
c.forceUpdate()
c.isMounted()
Methods
{
render: function()
getInitialState: function()
getDefaultProps: function()
mixins: []
propTypes: {} / for validation /
statics: { .. } / static methods /
displayName: '..' / automatically filled in by jsx /
}
Lifecycle
componentWillMount()
componentDidMount()
// not on initial render
componentWillReceiveProps(props)
shouldComponentUpdate(props, state)
componentWillUpdate(props, state)
componentDidUpdate(prevProps, prevState)
componentWillUnmount()
// ...there is no DidUnmount or ReceiveState.
Initial States
React.createClass({
getInitialState: function () {
return {data: []};
},
render: function () {
return (
<CommentList data={this.state.data} />
);
}
});
Default Properties
React.createClass({
getDefaultProps: function () {
return {name: ''};
}
);
Before Rendering
React.createClass({
componentWillMount: function () {
$.get(this.props.url, function (data) {
this.setState(data);
});
},
render: function () {
return (
<CommentList data={this.state.data} />
);
}
});
Actions
<form onSubmit={this.handleSubmit}>
Name: <input ref="name">
</form>
React.createClass({
handleSubmit: function (event) {
name = this.refs['name'].getDOMNode().value;
// see two-way binding below
}
})
Two-way binding
React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {value: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('value')} />;
}
});
// LinkedStateMixin adds a method to your React component called
// linkState().
Lists
var TodoList = React.createClass({
render: function() {
var createItem = function(itemText) {
return <li>{itemText}</li>;
};
return <ul>{this.props.items.map(createItem)}</ul>;
}
});
Property validations
React.createClass({
propTypes: {
// required
requiredFunc: React.PropTypes.func.isRequired,
requiredAny: React.PropTypes.any.isRequired,
// primitives, optional by default
bool: React.PropTypes.bool,
func: React.PropTypes.func,
number: React.PropTypes.number,
string: React.PropTypes.string,
}
});
Class set
render: function() {
var cx = React.addons.classSet;
var classes = cx({
'message': true,
'message-important': this.props.isImportant,
'message-read': this.props.isRead
});
// same final string, but much cleaner
return <div className={classes}>Great Scott!</div>;
}
Propagating properties to children
var VideoPlayer = React.createClass({
render: function() {
return <VideoEmbed {...this.props} controls='false' />;
}
});
<VideoPlayer src="video.mp4" />
Mixins
var TickTock = React.createClass({
mixins: [SetIntervalMixin]
}
SetIntervalMixin = {
componentWillMount: function() { .. }
}
Webpack Cheat Sheet
package.json
{
"name": "webpack-cheatsheet",
"version": "0.0.1",
"description": "Ekino Webpack Cheat Sheet Project",
"dependencies": {
"react": "^0.13",
"lodash": "~3.10"
},
"devDependencies": {
"babel": "~5.8",
"babel-loader": "~5.3",
"clean-webpack-plugin": "^0.1.3",
"css-loader": "^0.18",
"extract-text-webpack-plugin": "^0.8.2",
"file-loader": "^0.8.4",
"font-awesome": "^4.4.0",
"html-webpack-plugin": "^1.6.1",
"node-sass": "^3.2",
"path": "^0.12.7",
"react-hot-loader": "^1.3.0",
"react-intl": "^1.2",
"resolve-url-loader": "^1.1.0",
"sass-loader": "^2.0",
"style-loader": "^0.12",
"webpack": "~1.12",
"webpack-dev-server": "^1.11.0"
},
"scripts": {
"webpack": "node webpack.config.js"
}
}
webpack.config.js
{
"name": "webpack-cheatsheet",
"version": "0.0.1",
"description": "Ekino Webpack Cheat Sheet Project",
"dependencies": {
"react": "^0.13",
"lodash": "~3.10"
},
"devDependencies": {
"babel": "~5.8",
"babel-loader": "~5.3",
"clean-webpack-plugin": "^0.1.3",
"css-loader": "^0.18",
"extract-text-webpack-plugin": "^0.8.2",
"file-loader": "^0.8.4",
"font-awesome": "^4.4.0",
"html-webpack-plugin": "^1.6.1",
"node-sass": "^3.2",
"path": "^0.12.7",
"react-hot-loader": "^1.3.0",
"react-intl": "^1.2",
"resolve-url-loader": "^1.1.0",
"sass-loader": "^2.0",
"style-loader": "^0.12",
"webpack": "~1.12",
"webpack-dev-server": "^1.11.0"
},
"scripts": {
"webpack": "node webpack.config.js"
}
}
webpack.config.js
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require('webpack');
var path = require('path');
var WebpackDevServer = require('webpack-dev-server');
var CleanPlugin = require('clean-webpack-plugin');
// Make sure the NODE_ENV is always set
// If the file is call directly with node (node webpack.config.js) then the hot loader server will
// be started and you can enjoy live editing.
// if you call webpack command line then the production files will be created
process.env.NODE_ENV = process.env.NODE_ENV || (require.main === module ? 'development' : 'production');
// configure host settings for the WebDevServer
var devserver = {ip: 'localhost', port: 3000};
var config = {
// we use path.join to make it work cross plateform
context: path.join(__dirname, 'src'),
entry: process.env.NODE_ENV == 'production' ? {
app: ["./index.jsx"]
} : {
// WebpackDevServer is only required on development, with key value entry mode, the
// webpack/hot/only-dev-server entry is required on each entry.
app: ["./index.jsx", 'webpack/hot/only-dev-server'],
// The client entry is used to serve an iframe with reloading information
// The final url will be http://localhost:3000/webpack-dev-server
client: 'webpack-dev-server/client?http://'+devserver.ip+':'+devserver.port
},
output: {
// Assets destination
path: path.join(__dirname, 'dist'),
// The final entry file is located in dist/js folder
// The name variable will the key used in the entry index
// The hash is optional, but usefull for having unique url for caching purpose
filename: "js/[name]-[hash:8].js",
// require to make the specific fonts work (absolute path),
// the value is also used by the WebpackDevServer to serve assets
publicPath: "/"
},
resolve: {
// the fallback array contains a set of folder used by webpack to search
// available assets used with the require keyword
fallback: [
path.join(__dirname, 'src')
],
// This is important if you want to refer to module resources. It is important
// to use ~ symbol to reference module: @import "~font-awesome/scss/font-awesome";
modulesDirectories: ['node_modules']
},
module: {
// The loaders section defines how webpack behaves when a resource need to be loaded.
// A resource is anything loaded with the require keyword
loaders: [{
// regular expression to match only jsx file
test: /\.jsx?$/,
exclude: /(node_modules)/,
// The include keyword is used to limit the lookup scope used by webpack
// with the hot reload configuration.
include: path.join(__dirname, 'src'),
// In production, we don't need react-hot as it include a lot of code.
loaders: process.env.NODE_ENV == 'production' ?
['babel'] :
['react-hot', 'babel']
}, {
test: /\.scss$/,
// resolve-url allow to resolve url() please keep it mind to set the output.publicPath
// to use absolute path. This is usefull is you have fonts and css folders on
// different folders
loader: process.env.NODE_ENV == 'production' ?
// the plugin is used to store css content to an external file
// without this plugin css will be store as a variable inside the final
// bundle file
ExtractTextPlugin.extract('css!resolve-url!sass') :
// the style loader is usefull to load the style inline with WebpackDevServer
'style!css!resolve-url!sass'
}, {
// match woff fonts
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// the file loader will copy the font into a dedicated folder
// with the name argument it is possible to define a target to store the file
// if the output.publicPath is set, then the final reference will be output.publicPath + name
loader: "file?name=fonts/[name]-[hash:8].[ext]"
}, {
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// the -loader suffix is optional so file or file-loader is equivalent
loader: "file-loader?name=fonts/[name]-[hash:8].[ext]"
}, {
test: /\.png$/,
loader: "url?limit=100000"
}, {
test: /\.jpg$/,
loader: "file"
}]
},
plugins: [
// this plugin will append on generated file the provided string, this can be useful
// for copyright holder
new webpack.BannerPlugin("This code is part of the Ekino Webpack Cheat Sheet Project", {
raw: false,
entryOnly: false
}),
// this plugin must be used with the loader ExtractTextPlugin.extract
// the final file will use the entry name and the hash for current
// entry file
new ExtractTextPlugin("css/[name]-[id]-[contenthash:8].css", {
allChunks: true
}),
// the plugin will generate the index file inside the dist folder. The plugin
// can inject all related js and css assets.
new HtmlWebpackPlugin({
inject: true,
title: 'Ekino Webpack Cheat Sheet Project',
template: 'src/index.html',
filename: 'index.html'
}),
// this plugin will compute common chunks from entry files and related chunks to
// optimize and reduce final file size
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
filename: "js/[name]-[hash:8].js",
chunks: [] // entries to use
}),
new webpack.DefinePlugin({
VERSION: JSON.stringify("0.0.1-DEV"),
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}
}),
// clean the dist folder before building assets
new CleanPlugin(['dist'], __dirname)
]
};
if ('development' === process.env.NODE_ENV) {
// define how assets will be available, the eval value is useful with the
// HotModuleReplacementPlugin to reload code on change
config.devtool = 'eval';
config.plugins.push(new webpack.HotModuleReplacementPlugin());
}
if ('production' === process.env.NODE_ENV) {
// reduce the final size of javascript files
config.plugins.push(new webpack.optimize.UglifyJsPlugin({
compress: {
// warning: false
},
mangle: { // default values
except: ['$super', '$', 'exports', 'require']
}
}));
}
// make the config available so webpack can grab the configuration
module.exports = config;
// start the WebpackDevServer which handle hot reload
if (require.main === module && 'development' === process.env.NODE_ENV ) { // if call from node directly we start the dev webserver
var server = new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
stats: {
colors: true
},
progress: true
});
server.listen(devserver.port, devserver.ip, function (err, result) {
if (err) {
console.log(err);
}
console.log('Listening at http://'+devserver.ip+':'+devserver.port+'/webpack-dev-server/');
});
}
Установка TypeScript, React, Webpack
Структура проекта.
proj/
+- node.exe
|
+- node_modules
| +- npm/
|
+- npm.cmd
|
+- src/
| +- components/
|
+- dist/
Создание структуры проекта из командной строки cmd.
mkdir proj
cd proj
mkdir src
cd src
mkdir components
cd ..
mkdir dist
Создание package.json из командной строки cmd.
npm init
Содержимое package.json.
{
"version": "1.0.0"
, "name": "webpack-typescript-react"
, "description": "Webpack Typescript React"
, "engines": {
"node": "6.3.1"
, "npm": "3.10.6"
}
, "dependencies": {
"typescript": "1.8.10"
, "typings": "1.3.2"
, "webpack": "1.13.1"
, "ts-loader": "0.8.2"
, "source-map-loader": "0.1.5"
, "react": "15.3.0"
, "react-dom": "15.3.0"
}
}
Создать в папке proj файл .typingsrc с содержимым:
{
"rejectUnauthorized": false
}
Установка файлов d.ts из командной строки cmd.
В папке proj создадим файл index.html с содержимым:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<!-- Зависимости -->
<script src="./node_modules/react/dist/react.js"></script>
<script src="./node_modules/react-dom/dist/react-dom.js"></script>
<!-- Главный файл -->
<script src="./dist/bundle.js"></script>
</body>
</html>
Запустим сборку проекта из командной строки cmd.
webpack
node.exe
node_modules
npm.cmd
package.json
.typingsrc
tsconfig.json
typings.json
webpack.config.js
tsc.cmd
typings.cmd
webpack.cmd
typings
src
dist
index.html
proj/
+- node.exe
|
+- node_modules
| +- npm/
|
+- npm.cmd
|
+- src/
| +- components/
|
+- dist/
Создание структуры проекта из командной строки cmd.
mkdir proj
cd proj
mkdir src
cd src
mkdir components
cd ..
mkdir dist
Создание package.json из командной строки cmd.
npm init
Содержимое package.json.
{
"version": "1.0.0"
, "name": "webpack-typescript-react"
, "description": "Webpack Typescript React"
, "engines": {
"node": "6.3.1"
, "npm": "3.10.6"
}
, "dependencies": {
"typescript": "1.8.10"
, "typings": "1.3.2"
, "webpack": "1.13.1"
, "ts-loader": "0.8.2"
, "source-map-loader": "0.1.5"
, "react": "15.3.0"
, "react-dom": "15.3.0"
}
}
Установка библиотек из командной строки cmd.
npm install typescript
npm install typings
npm install webpack
npm install ts-loader
npm install source-map-loader
npm install react
npm install react-dom
Удалить папки и файлы
proj/etc
proj/typings
proj/tsc
proj/tsserver
proj/tsserver.cmd
proj/webpack
{
"rejectUnauthorized": false
}
Установка файлов d.ts из командной строки cmd.
typings install --save react
typings install --save react-dom
Эти команды создадут папку typings и файл typings.json.
Создать в папке proj файл tsconfig.json с содержимым:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es5",
"jsx": "react"
},
"files": [
"./typings/index.d.ts",
"./src/components/Hello.tsx",
"./src/index.tsx"
]
}
Создать в папке proj файл webpack.config.js с содержимым:
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "./dist/bundle.js",
},
// Включить sourcemaps для отладки вывода webpack.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// Все файлы с расширениями '.ts' и '.tsx' будут обработаны 'ts-loader'.
{ test: /\.tsx?$/, loader: "ts-loader" }
],
preLoaders: [
// Все итоговые файлы '.js', имеющие sourcemaps будут обработаны 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
// При импорте модуля, чей путь соответствует одному из ниже приведенных,
// просто предположим, что он уже загружен и не будем добавлять его в пакет,
// что позволит браузеру кэшировать библиотеки между сборками проекта.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
В папке proj/src/components создадим файл Hello.tsx с содержимым:
import * as React from 'react';
export interface HelloProps {
compiler: string;
framework: string;
}
export class Hello extends React.Component<HelloProps, {}> {
render() {
return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
}
}
В папке proj/src создадим файл index.tsx с содержимым:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {Hello} from './components/Hello';
ReactDOM.render(
<Hello compiler="TypeScript" framework="React" />,
document.getElementById('example')
);
В папке proj создадим файл index.html с содержимым:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<!-- Зависимости -->
<script src="./node_modules/react/dist/react.js"></script>
<script src="./node_modules/react-dom/dist/react-dom.js"></script>
<!-- Главный файл -->
<script src="./dist/bundle.js"></script>
</body>
</html>
Запустим сборку проекта из командной строки cmd.
webpack
Эта команда создаст папку dist с файлами bundle.js и bundle.js.map в ней.
Итоговый состав содержимого папки proj:
node_modules
npm.cmd
package.json
.typingsrc
tsconfig.json
typings.json
webpack.config.js
tsc.cmd
typings.cmd
webpack.cmd
typings
src
dist
index.html
пятница, 29 июля 2016 г.
Краткий перечень API Node.js
=======================================
| Cheat sheet small - краткая подсказка
=======================================
npm init
npm install --save gulp
npm uninstall --save gulp
npm update
npm list
global
require
export
module.exports
assert()
console.log()
process.argv
process.stdout.write()
porcess.stderr.write()
porcess.stdin
process.exit()
process.stdout.clearLine()
process.stdout.cursorTo()
child_porcess.spawn()
child_process.exec()
var emeitter = new events.EventEmitter();
emeitter.on()
emeitter.once()
emeitter.addListener()
emeitter.removeListener()
emeitter.emit()
setTimeout()
setInterval()
setImmediate()
Buffer
__filename
__dirname
path
fs.writeFile()
fs.appendFile()
fs.readFile()
fs.rename()
fs.unlink()
fs.stat.isFile()
fs.stat.isDirectory()
fs.readdir()
fs.mkdir()
fs.rename()
fd.rmdir
fs.createReadStream()
fs.createWriteStream()
writeStream.write()
readStream.pipe()
url.parse()
url.format()
querystring.parse(
querystring.stringify()
querystring.escape()
querystring.unescape()
http.request()
http.createServer()
bodyParser()
os
debugger
=======================================
| Cheat sheet big - большая подсказка
=======================================
// NPM
npm init
npm install --save gulp
npm uninstall --save gulp
npm update
npm list
// Global, __dirname, __filename
console.log(global); // аналог window
console.log(__dirname); // абсолютный путь до папки из которой запущен данный файл
console.log(__filename); // абсолютный путь до данного файла
console.log(process.argv); // массив аргументов
// Process, stdout, stderr, stdin
process.stdout.write(`\n\n\n${__filename}\n\n\n`); // аналог console.log()
process.stderr.write(`\n\n\n${__dirname}\n\n\n`); // аналог console.error()
process.stdin.on("data", function (data) {
process.stdout.write(data.toString());
process.exit();
});
process.on("exit", function () {
process.stdout.write("Goodbye");
});
process.stdout.clearLine(); // очистить текущую строку выводы в окне терминала
process.stdout.cursorTo(0); // переместить курсор в окне терминала на позицию 0
// Дочерний процесс - выполнить команду для терминала - exec
var exec = require("child_process").exec; // выполнить команду для терминала
var command = "open http://www.goggle.com"; // команда для терминала
exec(command, function (error, stdout) {
if (error) {throw error;}
console.log("Done");
console.log(stdout);
});
// Дочерний процесс - запустить дочерний процесс - spawn
var spawnProcess = require("child_process").spawn;
var terminalCommand = "node";
var options = ["script-file.js", "say", "hi!"];
var childProcess = spawn(terminalCommand, options);
childProcess.stdout.on("data", function (data) {
console.log(data.toString());
});
childProcess.on("close", function () {
console.log("Done");
process.exit();
});
setTimeout(function(){
childProcess.stdin.write("stop"); // выполнить команду в консоли дочернего процесса
}, 5000);
// Модули - require, export, module.exports
var moduleFile = require("moduleFile"); // пути: ./ - текущая папка, ../ - внешняя папка, / - внутренняя папка
export var a = 1;
export function b () {}
module.exports = {a: a, b: b}; // аналог return из RequireJS
// События - on, once, emit, addListener, removeListener
var events = require("events");
var emitter = new events.EventEmitter();
emitter.on("say", function say (message) {});
emitter.once("say", function say (message) {});
emitter.addListener("say", function say (message) {});
emitter.removeListener("say", say);
emitter.emit("say", "Hello World");
// Работа с файлами - получение списка файлов, находящихся в папке - readdir
var fs = require("fs");
var files = readdirSync("./some/folder");
console.log(files);
readdir("./some/folder", function (error, files) {
if (error) {throw error;}
console.log(files);
});
// Работа с файлами - чтение содержимого файла - readFile
var fs = require("fs");
var fileContent = fs.readFileSync("./some/file.txt", "UTF-8"); // кодировку нужно указывать !!!
console.log(fileContent);
readFile("./some/file.txt", "UTF-8", function (error, fileContent) {
if (error) {throw error;}
console.log(fileContent);
});
// Работа с файлами - получение описания файла stat
var fs = require("fs");
var path = require("path");
fs.readdir("./libs", function (error, files) {
if (error) {throw error;}
files.forEach(function (fileName) {
var file = path.join(__dirname, "libs", fileName); // абсолютный путь до файла
var stats = fs.statSync(file);
if (stats.isFile()) {
fs.readFile(file, "UTF-8", function (error, fileContent) {
if (error) {throw error;}
console.log(fileContent);
});
} else if (stats.isDirectory()) {
console.log("It is directory");
}
});
});
// Работа с файлами - создание файла и запись в файл - writeFile
var fs = require("fs");
var fileContent = "Hello World";
fs.writeFileSync("sample.txt", fileContent);
console.log("Done");
fs.writeFile("sample.txt", fileContent, function (error) {
if (error) {throw error;}
console.log("Done");
});
fs.appendFile("sample.txt", "\nGoodbye");
// Работа с файлами - переименование и перемещение файлов в другую папку - rename
var fs = require("fs");
fs.renameSync("./lib/file-1.js", "./lib/file-2.js"); // переименование файла
console.log("Файл переименован");
fs.rename("./lib/file-1.js", "./file-1.js", function (error) { // перемещение файла в другую папку
if (error) {throw error;}
console.log("Файл пемемещен в другую папку");
});
// Работа с файлами - удаление файлов - unlink
var fs = require("fs");
try {
fs.unlinkSync("./lib/file-1.js"); // удаление файла
console.log("Done");
} catch (error) {
console.log(error);
}
fs.unlink("./lib/file-1.js", function (error) { // удаление файла
if (error) {throw error;}
console.log("Done");
});
// Работа с файлами - создание директорий - mkdir, exists
var fs = require("fs");
if (fs.existsSync("lib")) {
console.log("Directory lib already exists");
} else {
fs.mkdir("libs", function (error) {
if (error) {throw error;}
console.log("Directory created");
});
}
// Работа с файлами - переименование и перемещение папок в другую папку - rename
var fs = require("fs");
fs.renameSync("./assets/logs", "./logs"); // перемещение папки в другую папку
console.log("Done");
// Работа с файлами - удаление папки - rmdir - НЕЛЬЗЯ УДАЛИТЬ ПАПКУ, ЕСЛИ В НЕЙ ЕЩЕ ЕСТЬ ФАЙЛЫ! СНАЧАЛА НАДО УДАЛИТЬ ВСЕ ФАЙЛЫ!
var fs = require("fs");
var files = fs.readdirSync("./libs");
if (files.length > 0) {
files.forEach(function (fileName) {
fs.unlinkSync("./libs" + fileName);
});
}
fs.rmdir("./libs", function (error) {
if (error) {throw error;}
console.log("Done");
});
// Потоки - readable, writable, duplex = readable + writable
// Потоки - создание потока для чтения данных - createReadStream
var fs = require("fs");
var readStream = fs.createReadStream("./chat.log", "UTF-8"); // прочитать содержимое файла в потоке
var fileContent = "";
readStream.on("data", function (chunk) {
fileContent += chunk;
process.stdout.write(chunk);
});
readStream.on("end", function () {
console.log("Done");
});
// Потоки - создание потока для записи данных - createWriteStream
var fs = require("fs");
var writeSteam = fs.createWriteStream("./chat.log");
for (var i = 0; i < 1000; i++) {
writeStream.write(Math.random());
}
// HTTP - клиентский запрос - request
var http = require("http");
var fs = require("fs");
var options = {
hostname: "google.com",
post: 80
path: "/search/data",
method: "GET"
};
var request = http.request(options, function (response) {
response.setEncoding("UTF-8");
console.log(response.statusCode);
console.log(response.headers);
var responseBody = "";
response.on("data", function (chunk) {
responseBody += chunk;
});
response.on("end", function () {
fs.writeFile("some.html", responseBody, function (error) {
if (error) {throw error;}
console.log("File downloaded");
});
});
});
request.on("error", function () {
console.log("Error in request");
});
request.end(); // Послать запрос на сервер
// HTTP - создание сервера - createServer
var http = require("http");
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<!DOCTYPE html>");
response.end(); // Завершить отправку ответа
});
server.listen("127.0.0.1:80"); // Создать сервер
// HTTP - обслуживание файлов - writeHead, write, end, url, method
var http = require("http");
var fs = require("fs");
var path = require("path");
var server = http.createServer(function (request, responce) {
console.log(respose.method);
if (requres.url === "/") {
fs.readFile("./public/index.html", "UTF-8", function (error, fileContent) {
if (error) {throw error;}
response.writeHead(200, {"Content-Type": "text/html"});
response.end(fileContent);
});
} else if (request.url.match(/.css$/)) {
var cssPath = path.join(__dirname, "public", request.url);
var readFileStream = fs.createReadStream(cssPath, "UTF-8"); // текстовые данные
response.writeHead(200, {"Content-Type": "text/css"});
readFileStream.on("data", function (chunk) {
response.write(chunk);
});
readFileStream.on("end", function () {
response.end();
});
// или можно так
// readFileStream.pipe(response); // автоматически ставит в конце response.end()
} else if (request.url.match(/.jpg$/)) {
var imagePath = path.join(__dirname, "public", request.url);
var readFileStream = fs.createReadStream(imagePath); // бинарные данные
response.writeHead(200, {"Content-Type": "image/jpeg"});
readFileStream.pipe(response);
} else {
response.writeHead(404, {"Content-Type": "text/plain"});
response.end("404 File Not Found");
}
console.log(request);
});
server.listen("127.0.0.1:80");
// HTTP - обслуживание JSON - writeHead, write, end, url, method
var http = require("http");
var data = require("./json-file");
var server = http.createServer(function (request, response) {
if (request.url === "/") {
response.writeHead(200, {"Content-Type": "text/json"});
response.end(JSON.stringify(data));
} else if (request.url === "/instock") {
listInStock(response);
} else if (requrest.url === "/onorder") {
listOnBackOrder(response);
} else {
response.writeHead(404, {"Content-Type": "text/plain");
response.end("404 File Not Found");
}
});
server.listen("127.0.0.1:80");
function listInStock (response) {
var inStock = data.filter(function (item) {
return item.available === "In stock";
});
response.writeHead(200, {"Content-Type": "text/json"});
reponse.end(JSON.stringify(inStock));
}
function listOnBackOrder (response) {
var onOrder = data.filter(function (item) {
return item.available === "On back order";
});
response.writeHead(200, {"Content-Type": "text/json"});
reponse.end(JSON.stringify(onOrder));
}
// HTTP - обслуживание GET, POST - writeHead, write, end, url, method
var http = require("http");
var fs = require("fs");
var server = http.createServer(function (request, response) {
if (request.method === "GET") {
response.writeHead(200, {"Content-Type": "text/html"});
var fileReadStream = fs.createReadStream("./public/form.html", "UTF-8");
fileReadStream.pipe(response);
} else if (request.method === "POST") {
var body = "";
request.on("data", function (chunk) {
body += chunk;
});
request.on("end", function () {
response.writeHead(200, {"Content-Type": "text/html"});
reponse.end(body);
});
}
});
server.listen("127.0.0.1:80");
// Express - сервер и прослойки middleware - app, use, get, post, delete, static, bodyParser
var express = require("express");
var app = express();
app.use(express.static("./public"));
app.use(epress.bodyParser({uploadDir: "./upload"}));
app.use(function (request, response, next) {
console.log(request.method);
console.log(request.url);
next();
});
app.get("/", function (request, response) {
response.json({one: 1, two: 2});
});
app.post("/form", function (request, response) {
response.end("<!DOCTYPE html>" + request.body);
});
app.delete("/delete/:id", function (request, response) {
response.end(request.params.id);
});
app.listen("127.0.0.1:80");
module.exports = app;
// WebSockets - стронняя библиотека WS для работы с WebSockets - WebSocketServer, send
var WebSocketServer = require("ws");
var wss = new WebSocketServer({port: 80});
wss.on("connection", function (webSocket) {
webSocket.on("message", function (message) {
if (message === "exit") {
webSocket.close();
} else {
wss.clients.forEach(function (client) {
client.send(message);
});
}
});
webSocket.send("Welcome to chat");
});
// Socket.IO - стронняя библиотека Socket.IO для работы с WebSockets - emit
var express = require("express");
var http = require("http");
var io = require("socket.io");
var app = express();
var server = http.createServer(app).listen("127.0.0.1:80");
io(server);
app.use(express.static("./public"));
io.on("connection", function (socket) {
socket.on("chat", function (message) {
socket.broadcast.emit("message", message);
});
socket.emit("message", "Welcome to chat");
});
=======================================
| Assertion Testing - ассерты для тестирования
=======================================
const assert = require('assert');
assert(false, 'it is false'); // throws: AssertionError: it is false
assert.ok(false, 'it is false'); // throws: AssertionError: it is false
assert.equal({a: {b: 1}}, {a: {b: 1}}); // throws: AssertionError: { a: { b: 1 } } == { a: { b: 1 } }
assert.strictEqual(1, '1'); // throws: AssertionError: 1 === '1'
assert.deepEqual({a: {b: 1}}, {a: {b: 2}}; // throws: AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }
assert.deepStrictEqual({a: 1}, {a: '1'}); // throws: AssertionError: { a: 1 } deepStrictEqual { a: '1' }
assert.fail(1, 2, undefined, '>'); // throws: AssertionError: 1 > 2
assert.fail(1, 2, 'whoops', '>'); // throws: AssertionError: whoops
assert.notEqual(1, 1); // throws: AssertionError: 1 != 1
assert.notStrictEqual(1, 1); // throws: AssertionError: 1 != 1
assert.notDeepEqual({a: {b: 1}}, {a: {b: 1}}); // throws: AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }
assert.notDeepStrictEqual({a: '1'}, {a: '1'}); // throws: AssertionError: { a: '1' } notDeepStrictEqual { a: '1' }
=======================================
| Buffer - буферы - массивы для двоичных данных
=======================================
const buf = Buffer.alloc(10); // <Buffer 00 00 00 00 00 00 00 00 00 00>
const buf = Buffer.alloc(10, 1); // <Buffer 01 01 01 01 01 01 01 01 01 01>
const buf = Buffer.from([1, 2, 3]); // <Buffer 01 02 03>
const buf = Buffer.from('test', 'utf8'); // <Buffer 74 65 73 74>
const buf = Buffer.from('hello world', 'ascii');
Варианты метода from:
- Buffer.from(array);
- Buffer.from(buffer);
- Buffer.from(arrayBuffer[, byteOffset [, length]]);
- Buffer.from(str[, encoding]);
const buf = Buffer.from([1, 2, 3]);
for (var b of buf) {
console.log(b);
}
// Prints:
// 1
// 2
// 3
console.log(buf.toString('hex')); // prints: 68656c6c6f20776f726c64
console.log(buf.toString('base64')); // prints: aGVsbG8gd29ybGQ=
Варианты кодировок:
- 'ascii'
- 'utf8'
- 'utf16le'
- 'ucs2'
- 'base64'
- 'binary'
- 'hex'
const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);
console.log(buf.length); // Prints: 16
const buf = Buffer.from([1, 2, 3]); // <Buffer 01 02 03>
buf[1] = 5; // <Buffer 01 05 03>
console.log(buf.compare(buf)); // Prints: 0
console.log(buf1.equals(buf2)); // Prints: true
buf1.copy(buf2, 8, 16, 20);
const buf = Buffer.allocUnsafe(10);
buf.fill('h');
console.log(buf.toString()); // Prints: hhhhhhhhhh
const buf = Buffer.from('this is a buffer');
buf.indexOf('this'); // returns 0
buf.indexOf('is'); // returns 2
buf.lastIndexOf('this'); // returns 0
buf.lastIndexOf('buffer'); // returns 17
buf.includes('this'); // returns true
const buf = Buffer.from('buffer');
for (var key of buf.keys()) {
console.log(key);
}
// prints:
// 0
// 1
// 2
// 3
// 4
// 5
Buffer.isBuffer(obj) // true или false
const buf = Buffer.alloc(1234);
console.log(buf.length); // Prints: 1234
const buf2 = buf1.slice(0, 3);
const buf = Buffer.alloc(3, 1); // <Buffer 01 01 01>
buf.toJSON(); // {type: 'Buffer', data: [1, 1, 1]}
const buf = Buffer.from('buffer');
for (var value of buf.values()) {
console.log(value);
}
// prints:
// 98
// 117
// 102
// 102
// 101
// 114
const buf = Buffer.allocUnsafe(256);
const len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); // Prints: 12 bytes: 1/2 + 1/4 = 3/4
const buf = Buffer.alloc(3, 1); // <Buffer 01 01 01>
buf.inspect(); // <Buffer 01 01 01>
buffer.INSPECT_MAX_BYTES; // Default: 50
=======================================
| Child Processes - работа с окном командной строки и запуск дополнительных дочерних процессов Node.js
=======================================
child_process.exec() - асинхронно запускает окно командной строки и выполняет внутри него команду, передавая stdout и stderr в callback
function когда выполнение команды завершится.
child_process.execFile() - такой же как child_process.exec() за исключением того, что команда выполняется напрямую без запуска окна
командной строки.
child_process.execSync() - синхронная версия child_process.exec(), блокирующая Node.js event loop.
child_process.execFileSync() - синхронная версия child_process.execFile(), блокирующая Node.js event loop.
child_process.fork() - запускает новый отдельный процесс Node.js и открывает канал для передачи сообщений между родительским процессом
Node.js и дочерним процессом Node.js.
child_process.spawn() - асинхронно запускает дочерний процесс Node.js, передавая stdout и stderr в callback function когда выполнение
команды завершится.
child_process.spawnSync() - синхронная версия child_process.spawn(), блокирующая Node.js event loop до завершения выполнения дочернего
процесса.
Достыпные Events:
- on('data, function () {})
- on('close', function () {})
- on('disconnect', function () {})
- on('error', function () {})
- on('exit', function () {})
- on('message', function () {})
Методы:
- child.send(message[, sendHandle[, options]][, callback])
- child.connected
- child.disconnect()
- child.kill([signal])
- child.pid
- child.stderr
- child.stdin
- child.stdio
- child.stdout
Примеры:
const spawn = require('child_process').spawn;
const listProcess = spawn('ls', ['-lh', '/usr']);
listProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
listProcess.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
listProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
// Excute gulp task
var task = process.argv.slice(2).join(' ')
, command = 'node ./node_modules/gulp/bin/gulp.js ' + task
, childProcess = require('child_process').exec(command);
childProcess.stdout.on('data', function (data) {console.log(data);});
childProcess.stderr.on('data', function (data) {console.log(data);});
childProcess.on('data', function (code) {if (code === 0) {console.log('Done');} else {console.log('Exit code: ' + code);}});
// или
const exec = require('child_process').exec;
exec('cat *.js bad_file | wc -l', function (error, stdout, stderr) {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
// execFile
const execFile = require('child_process').execFile;
const child = execFile('node', ['--version'], function (error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
});
=======================================
| Console - console.log() - вывод сообщений на консоль
=======================================
console.log('hello world'); // Prints: hello world, to stdout
console.log('hello %s', 'world'); // Prints: hello world, to stdout
console.info([data][, ...]) - тоже самое, что и console.log([data][, ...])
console.dir(obj[, options]) // печатает свойства объекта
console.trace('Show me'); // Prints: (stack trace will vary based on where trace is called)
const code = 5;
console.error('error #%d', code); // Prints: error #5, to stderr
console.error('error', code); // Prints: error 5, to stderr
console.warn([data][, ...]) - тоже самое, что и console.error([data][, ...])
console.assert(true, 'does nothing'); // OK
console.assert(false, 'Whoops %s', 'didn\'t work'); // AssertionError: Whoops didn't work
console.time('100-elements');
for (var i = 0; i < 100; i++) {}
console.timeEnd('100-elements'); // prints 100-elements: 225.438ms
=======================================
| Debugger - запуск отладчика debugger; в браузере для отладки скрипта Node.js
=======================================
Описание команд:
Команды перехода по коду:
cont, c - продолжить выполнения кода
next, n - перейти к следующему шагу
step, s - войти внутрь функции
out, o - выйти из функции
pause - поставить выполнение кода на паузу, как при нажатии на кнопку паузы в Chrome Developer Tools
Команды для расстановки точек остановок в коде:
setBreakpoint(), sb() - установить breakpoint на текущую линию кода
setBreakpoint(line), sb(line) - установить breakpoint конкретную линию кода
setBreakpoint('fn()'), sb(...) - установить breakpoint первую строчку внутри тела функции
setBreakpoint('script.js', 1), sb(...) - установить breakpoint первую строчку файлы script.js
clearBreakpoint('script.js', 1), cb(...) - удалить breakpoint в файле script.js с линии 1
// myscript.js
x = 5;
setTimeout(() => {
debugger;
console.log('world');
}, 1000);
console.log('hello');
// запуск отладки скрипта
$ node debug myscript.js
< debugger listening on port 5858
connecting... ok
break in /home/indutny/Code/git/indutny/myscript.js:1
1 x = 5;
2 setTimeout(() => {
3 debugger;
debug> cont
< hello
break in /home/indutny/Code/git/indutny/myscript.js:3
1 x = 5;
2 setTimeout(() => {
3 debugger;
4 console.log('world');
5 }, 1000);
debug> next
break in /home/indutny/Code/git/indutny/myscript.js:4
2 setTimeout(() => {
3 debugger;
4 console.log('world');
5 }, 1000);
6 console.log('hello');
debug> repl
Press Ctrl + C to leave debug repl
> x
5
> 2+2
4
debug> next
< world
break in /home/indutny/Code/git/indutny/myscript.js:5
3 debugger;
4 console.log('world');
5 }, 1000);
6 console.log('hello');
7
debug> quit
=======================================
| Events - события addListener(), removeListener(), emit()
=======================================
emitter.addListener(eventName, listener) - тоже самое, что и emitter.on(eventName, listener) - добавить событие
emitter.prependListener() - добавить событие в самое начало списка имеющихся событий
emitter.once(eventName, listener) - добавить событие, которое будет удалено сразу после его вызова
emitter.prependOnceListener() - добавить событие в самое начало списка имеющихся событий, которое будет удалено сразу после его вызова
emitter.emit(eventName[, arg1][, arg2][, ...]) - синхронно вызвать функции привязанные к события в порядке их привязки с передачей в них
аргументов
emitter.removeListener(eventName) - удалить событие
emitter.removeAllListeners([eventName]) - удалить все события
emitter.eventNames() - вернуть массив существующих имен событий
emitter.listenerCount(eventName) - подсчитать число существующих событий
emitter.getMaxListeners() - получить предельно допустимое число возможных событий (по умолчанию 10)
emitter.setMaxListeners(n) - установить предельно допустимое число возможных событий
emitter.listeners(eventName) - получить массив с копией функций привязанных к событию
// Пример добавления событий
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function callback (a, b) {
console.log(a, b, this);
// Prints:
// a b MyEmitter {
// domain: null,
// _events: { event: [Function] },
// _eventsCount: 1,
// _maxListeners: undefined }
});
myEmitter.emit('event', 'a', 'b');
myEmitter.removeEvent('event', callback);
// метод on
const myEmitter = new MyEmitter();
var m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event'); // Prints: 1
myEmitter.emit('event'); // Prints: 2
// метод once
const myEmitter = new MyEmitter();
var m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event'); // Prints: 1
myEmitter.emit('event'); // Ignored
// Error event
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!')); // Throws and crashes Node.js
=======================================
| Stream - end, read, write, pause, resume, pipe, unpipe
=======================================
const stream = require('stream');
Types of Streams:
- Readable - fs.createReadStream()
- Writable - fs.createWriteStream()
- Duplex - net.Socket
- Transform
Readable
readable.read([size])
readable.pause()
readable.resume()
readable.isPaused()
readable.pipe(destination[, options])
readable.unpipe([destination])
readable.setEncoding(encoding)
readable.wrap(stream)
readable.unshift(chunk)
Readable Events
- 'close'
- 'data'
- 'end'
- 'error'
- 'readable'
Writable
writable.write(chunk[, encoding][, callback])
writable.end([chunk][, encoding][, callback])
writable.cork()
writable.uncork()
writable.setDefaultEncoding(encoding)
Writable Events
- 'close'
- 'drain'
- 'error'
- 'finish'
- 'pipe'
- 'unpipe'
=======================================
| File System - open, close, readFile, writeFile, appendFile unlink, stats, access, watch
=======================================
// Создать поток для чтения из файла
fs.createReadStream(path[, options])
// Создать поток для записи в файл
fs.createWriteStream(path[, options])
// Открыть файл
fs.open(path, flags[, mode], callback)
// Закрыть файл
fs.close(fd, callback)
// Прочитать файл
fs.read(fd, buffer, offset, length, position, callback)
// Асинхронно прочитать весь файл целиком
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
// Прочитать содержимое директории
fs.readdir(path[, options], callback)
// Добавление текста в конец файла
fs.appendFile('message.txt', 'data to append', (err) => {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
// Усечь файл
fs.ftruncate(fd, len, callback)
// Записать данные в файл или создать новый файл
fs.write(fd, buffer, offset, length[, position], callback)
fs.write(fd, data[, position[, encoding]], callback)
// Записать данные в файл и заменить его на новый, если он уже существует
fs.writeFile(file, data[, options], callback)
// Переименовать файл
fs.rename(oldPath, newPath, callback)
// Проверить существует ли файл - deprecated
fs.exists('/etc/passwd', (exists) => {
console.log(exists ? 'it\'s there' : 'no passwd!');
});
// Сведения о файлах
fs.stat()
fs.lstat()
fs.fstat()
stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink() (only valid with fs.lstat())
stats.isFIFO()
stats.isSocket()
// Изменение атрибутов файла
fs.chmod(path, mode, callback)
// Изменение владельца файла
fs.chown(path, uid, gid, callback)
// Изменения атрибутов файла
fs.constants.F_OK - файл видим для текущего процесса (значение по умолчанию)
fs.constants.R_OK - файл можешт быть прочитан текущим процессом
fs.constants.W_OK - файл можешт быть записан текущим процессом
fs.constants.X_OK - файл можешт быть выполнен текущим процессом
fs.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK, (err) => {
console.log(err ? 'no access!' : 'can read/write');
});
// Отслеживание изменений файлов
fs.watch('./tmp', {encoding: 'buffer'}, (eventType, filename) => {
if (filename)
console.log(filename);
// Prints: <Buffer ...>
});
// Отслеживать изменения конкретного файла
fs.watchFile('message.text', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
// Скопировать файл
fs.link(srcpath, dstpath, callback)
// Асинхронная версия удаления файла
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('successfully deleted /tmp/hello');
});
// Синхронная версия удаления файла
const fs = require('fs');
fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');
// Создать директорию
fs.mkdir(path[, mode], callback)
// Удалить директорию
fs.rmdir(path, callback)
=======================================
| Path
=======================================
const path = require('path');
path.basename('/foo/bar/baz/asdf/quux.html') // returns 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', '.html') // returns 'quux'
path.win32..
path.posix..
path.delimiter
; for Windows
: for POSIX
path.sep
\ on Windows
/ on POSIX
// on POSIX:
'foo/bar/baz'.split(path.sep) // returns ['foo', 'bar', 'baz']
// on Windows:
'foo\\bar\\baz'.split(path.sep) // returns ['foo', 'bar', 'baz']
// on POSIX:
console.log(process.env.PATH) // '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'
process.env.PATH.split(path.delimiter) // returns ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
// on Windows:
console.log(process.env.PATH) // 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'
process.env.PATH.split(path.delimiter) // returns ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
path.dirname('/foo/bar/baz/asdf/quux') // returns '/foo/bar/baz/asdf'
path.extname('index.html') // returns '.html'
path.extname('index.coffee.md') // returns '.md'
path.extname('index.') // returns '.'
path.extname('index') // returns ''
path.extname('.index') // returns ''
path.format({dir: '/home/user/dir', base: 'file.txt'}); // returns '/home/user/dir/file.txt'
path.format({root: '/', base: 'file.txt'}); // returns '/file.txt'
path.format({root: '/', name: 'file', ext: '.txt'}); // returns '/file.txt'
path.format({base: 'file.txt'}); // returns 'file.txt'
path.format({root : "C:\\", dir : "C:\\path\\dir", base : "file.txt", ext : ".txt", name : "file"}); // returns 'C:\\path\\dir\\file.txt'
path.isAbsolute('/foo/bar') // true
path.isAbsolute('/baz/..') // true
path.isAbsolute('qux/') // false
path.isAbsolute('.') // false
path.isAbsolute('//server') // true
path.isAbsolute('C:/foo/..') // true
path.isAbsolute('bar\\baz') // false
path.isAbsolute('.') // false
ath.join('/foo', 'bar', 'baz/asdf', 'quux', '..') // returns '/foo/bar/baz/asdf'
path.join('foo', {}, 'bar') // throws TypeError: Arguments to path.join must be strings
path.normalize('/foo/bar//baz/asdf/quux/..') // returns '/foo/bar/baz/asdf'
path.normalize('C:\\temp\\\\foo\\bar\\..\\'); // returns 'C:\\temp\\foo\\'
// on POSIX:
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb') // returns '../../impl/bbb'
// on Windows:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb') // returns '..\\..\\impl\\bbb'
path.resolve('/foo/bar', './baz') // returns '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/') // returns '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif') // if the current working directory is /home/myself/node, this returns
'/home/myself/node/wwwroot/static_files/gif/image.gif'
// on POSIX:
┌───────────────────┬────────────┐
│ dir │ base │
├──────┬ ├─────┬──────┤
│ root │ │ name │ ext │
│ / home/user/dir / file .txt │
└──────┴───────────┴──────┴─────┘
path.parse('/home/user/dir/file.txt')
// returns
// {
// root : "/",
// dir : "/home/user/dir",
// base : "file.txt",
// ext : ".txt",
// name : "file"
// }
on Windows:
┌───────────── ──┬────────────┐
│ dir │ base │
├──────┬ ├──────┬─────┤
│ root │ │ name │ ext │
│ C:\ path\dir \ file .txt │
└──────┴──── ───┴──────┴─────┘
path.parse('C:\\path\\dir\\file.txt')
// returns
// {
// root : "C:\\",
// dir : "C:\\path\\dir",
// base : "file.txt",
// ext : ".txt",
// name : "file"
// }
=======================================
| Globals - __driname, __filename, global, Buffer, process, setTimeout, clearTimweout, console, module, exports, require
=======================================
console.log(__dirname); // /Users/mjr
console.log(__filename); // /Users/mjr/example.js
=======================================
| Modules - require, module, export, exports, name, id, parent, loaded
=======================================
require(X) from module at path Y
1. If X is a core module,
a. return the core module
b. STOP
2. If X begins with './' or '/' or '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.json is a file, parse X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
4. If X/index.node is a file, load X/index.node as binary addon. STOP
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
c. DIR = path join(PARTS[0 .. I] + "node_modules")
b. DIRS = DIRS + DIR
c. let I = I - 1
5. return DIRS
The module wrapper#
Before a module's code is executed, Node.js will wrap it with a function wrapper that looks like the following:
(function (exports, require, module, __filename, __dirname) {
// Your module code actually lives in here
});
module.filename
module.id
module.loaded
module.parent
module.require(id)
require.main === module
const circle = require('./circle.js');
console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
// assigning to exports will not modify module, must use module.exports
module.exports = (width) => {
return {
area: () => width * width
};
}
=======================================
| OS - EOL, platform, type, cpus, homedir, tmpdir
=======================================
const os = require('os');
os.EOL
\n on POSIX
\r\n on Windows
os.endianness()
'BE' for big endian
'LE' for little endian.
os.arch() - тоже самое, что и process.arch
// 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', 'x64', 'x86'
os.platform() - тоже самое, что и process.platform
// 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', 'win32'
os.type() // 'Linux' on Linux, 'Darwin' on OS X, 'Windows_NT' on Windows
os.release()
os.constants
os.cpus()
os.freemem() - число доступных байт системной памяти
os.totalmem() - общее число байт системной памяти
os.homedir() - домашняя директория в операционной системе
os.tmpdir() - директория для временных файлов в операционной системе
os.loadavg()
os.uptime()
os.networkInterfaces()
{
address: '127.0.0.1',
netmask: '255.0.0.0',
family: 'IPv4',
mac: '00:00:00:00:00:00',
internal: true
}
OS Constants:
- Signal Constants
- Error Constants
- POSIX Error Constants
- Windows Specific Error Constants
- libuv Constants
=======================================
| Process - argv, nextTick, exit, abort, stdin, stdout, stderr, chdir, cwd, env, hrtime
=======================================
process - это глобальный объект, экземляр Event Emitter, предоставляющий информацию и контролирующий текущий процесс работы Node.js
process.stdin
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write(`data: ${chunk}`);
}
});
process.stdin.on('end', () => {
process.stdout.write('end');
});
process.stdout
console.log = (msg) => {
process.stdout.write(`${msg}\n`);
};
process.stderr
process.nextTick(callback[, arg][, ...])
console.log('start');
process.nextTick(() => {
console.log('nextTick callback');
});
console.log('scheduled');
// Output:
// start
// scheduled
// nextTick callback
process.exit(1)
if (someConditionNotMet()) {
printUsageToStdout();
process.exit(1);
}
process.exitCode
process.kill(pid[, signal])
process.kill(process.pid, 'SIGHUP');
process.getegid()
if (process.getegid) {
console.log(`Current gid: ${process.getegid()}`);
}
process.geteuid()
process.getgid()
process.pid
process.title
process.abort()
process.argv
$ node process-2.js one two=three four
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`);
});
$ node --harmony script.js --version
['/usr/local/bin/node', 'script.js', '--version']
process.execArgv
$ node --harmony script.js --version
['--harmony']
process.execPath // /usr/local/bin/node
process.stdin.resume();
process.chdir(directory)
process.cwd()
console.log(`Current directory: ${process.cwd()}`);
process.chdir('/tmp');
console.log(`Starting directory: ${process.cwd()}`);
try {
process.chdir('/tmp');
console.log(`New directory: ${process.cwd()}`);
}
catch (err) {
console.log(`chdir: ${err}`);
}
process.hrtime([time])
var time = process.hrtime(); // [ 1800216, 25 ]
process.uptime()
process.versions
{
http_parser: '2.3.0',
node: '1.1.1',
v8: '4.1.0.14',
uv: '1.3.0',
zlib: '1.2.8',
ares: '1.10.0-DEV',
modules: '43',
icu: '55.1',
openssl: '1.0.1k'
}
process.config
process.connected
process.disconnect()
process.arch
process.platform
process.cpuUsage([previousValue])
const startUsage = process.cpuUsage(); // { user: 38579, system: 6986 }
process.release
process.env
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
process.env.foo = 'bar';
console.log(process.env.foo);
process.env.test = null;
console.log(process.env.test); // => 'null'
process.env.test = undefined;
console.log(process.env.test); // => 'undefined'
process.env.TEST = 1;
delete process.env.TEST;
console.log(process.env.TEST); // => undefined
process.mainModule
process.memoryUsage()
process.send(message[, sendHandle[, options]][, callback])
process.on('exit', (code) => {
console.log(`About to exit with code: ${code}`);
});
process.on('beforeExit', function () {});
process.on('disconnect', function () {});
process.on('message', function () {});
process.on('rejectionHandled', function () {});
const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, p) => {
unhandledRejections.set(p, reason);
});
process.on('rejectionHandled', (p) => {
unhandledRejections.delete(p);
});
process.on('uncaughtException', function () {});
process.on('uncaughtException', (err) => {
fs.writeSync(1, `Caught exception: ${err}`);
});
process.on('warning', function () {});
process.on('warning', (warning) => {
console.warn(warning.name); // Print the warning name
console.warn(warning.message); // Print the warning message
console.warn(warning.stack); // Print the stack trace
});
process.emitWarning('Something happened!'); // Prints: (node 12345) Warning: Something happened!
process.emitWarning('This API is deprecated', 'DeprecationWarning');
Signal Events
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit.');
});
=======================================
| HTTP - request, createServer, request, response, writeHead, write, end, setHeader, getHeader, removeHeader
=======================================
http.request(options[, callback])
http.createClient([port][, host])
http.createServer([requestListener])
http.globalAgent
http.get(options[, callback])
http.METHODS
http.STATUS_CODES
http.Agent
new Agent([options])
agent.createConnection(options[, callback])
agent.destroy()
agent.freeSockets
agent.getName(options)
agent.maxFreeSockets
agent.maxSockets
agent.requests
agent.sockets
http.ClientRequest
on('abort', function(){})
on('aborted', function(){})
on('checkExpectation', function(){})
on('connect', function(){})
on('continue', function(){})
on('response', function(){})
on('socket', function(){})
on('upgrade', function(){})
request.write(chunk[, encoding][, callback])
request.end([data][, encoding][, callback])
request.abort()
request.flushHeaders()
request.setNoDelay([noDelay])
request.setSocketKeepAlive([enable][, initialDelay])
request.setTimeout(timeout[, callback])
http.Server
on('checkContinue', function(){})
on('clientError', function(){})
on('close', function(){})
on('connect', function(){})
on('connection', function(){})
on('request', function(){})
on('upgrade', function(){})
server.listen(handle[, callback])
server.listen(path[, callback])
server.listen(port[, hostname][, backlog][, callback])
server.listening
server.close([callback])
server.maxHeadersCount
server.setTimeout(msecs, callback)
server.timeout
http.ServerResponse
on('close', function(){})
on('finish', function(){})
response.writeHead(statusCode[, statusMessage][, headers])
response.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/plain' });
response.write(chunk[, encoding][, callback])
response.end([data][, encoding][, callback])
response.setHeader(name, value)
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
response.getHeader(name)
var contentType = response.getHeader('content-type');
response.removeHeader(name)
response.removeHeader('Content-Encoding');
response.headersSent
response.setTimeout(msecs, callback)
response.statusCode
response.statusCode = 404;
response.statusMessage
response.statusMessage = 'Not found';
response.addTrailers(headers)
response.finished
response.sendDate
response.writeContinue()
http.IncomingMessage
on('aborted', function(){})
on('close', function(){})
message.headers
message.rawHeaders
message.setTimeout(msecs, callback)
message.statusCode
message.httpVersion
message.destroy([error])
message.method
message.rawTrailers
message.statusMessage
message.socket
message.trailers
message.url
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
var proxy = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
var srvUrl = url.parse(`http://${req.url}`);
var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {
// make a request to a tunneling proxy
var options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
var req = http.request(options);
req.end();
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
// ------------------------------------
const http = require('http');
// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', (req, socket, head) => {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n');
socket.pipe(socket); // echo back
});
// now that server is running
srv.listen(1337, '127.0.0.1', () => {
// make a request
var options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
req.on('upgrade', (res, socket, upgradeHead) => {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
// ----------------------------------------
const http = require('http');
const server = http.createServer((req, res) => {
res.end();
});
server.on('clientError', (err, socket) => {
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.listen(8000);
// ---------------------------------------
const server = http.createServer((req,res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
});
// -------------------------------------------------------
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
=======================================
| HTTPS -
=======================================
https.request(options, callback)
https.createServer(options[, requestListener])
https.Agent
https.Server
server.setTimeout(msecs, callback)
server.timeout
server.close([callback])
server.listen(handle[, callback])
server.listen(path[, callback])
server.listen(port[, host][, backlog][, callback])
https.get(options, callback)
https.globalAgent
// ---------------------------------------------
// curl -k https://localhost:8000/
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
// ---------------------------------------------
const https = require('https');
const fs = require('fs');
const options = {
pfx: fs.readFileSync('server.pfx')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
// ---------------------------------------------
const https = require('https');
https.get('https://encrypted.google.com/', (res) => {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
}).on('error', (e) => {
console.error(e);
});
// ---------------------------------------------
const https = require('https');
var options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET'
};
var req = https.request(options, (res) => {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
// ---------------------------------------------
var options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
options.agent = new https.Agent(options);
var req = https.request(options, (res) => {
...
});
=======================================
| Timers - setTimeout, setInterval, setImmediate, ref, unref
=======================================
var timeout = setTimeout(function(){}, 5000[, ...arg])
clearTimeout(timeout)
var interval = setInterval(function(){}, 5000[, ...arg])
clearInterval(interval )
var immediate = setImmediate(function(){}[, ...arg])
clearImmediate(immediate)
timeout.ref()
timeout.unref()
=======================================
| URL - парсинг урлов
=======================================
http://user:pass@host.com:8080/p/a/t/h?query=string#hash
┌───────────────────────────────────────────────────────────┐
│ href │
├───── ─┬┬─────── ┬─────────────┬───────────────────┬──────┤
│ protocol ││ auth │ host │ path │ hash │
│ ││ ├─────────────┼───── ───┬──────────┤ │
│ ││ │ hostname │ port │ pathname │ search │ │
│ ││ │ │ │ ├┬──────── ─┤ │
│ ││ │ │ │ │ │ query │ │
│ http: // user:pass @ host.com : 8080 /p/a/t/h ? query=string #hash │
│ ││ │ │ │ │ │ │ │
└───────┴┴─── ────┴────────┴────┴────── ─┴┴──────────┴─────┘
const url = require('url');
urlObject.href // 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
urlObject.protocol // 'http:'
urlObject.slashes // true
urlObject.host // 'host.com:8080'
urlObject.auth // 'user:pass
urlObject.hostname // 'host.com'
urlObject.port // '8080'
urlObject.pathname // '/p/a/t/h'
urlObject.search // ?query=string'
urlObject.path // '/p/a/t/h?query=string'
urlObject.query // 'query=string' или {'query': 'string'}
urlObject.hash '#hash'
url.format(urlObject) // возвращает отформатированную строку в адресом
url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) // берет строку с адресом и превращает её в объект URL object
url.resolve(from, to) // соединяет адрес страницы с адресом сайта
url.resolve('/one/two/three', 'four') // '/one/two/four'
url.resolve('http://example.com/', '/one') // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'
Пробелы и знаки < > " ` \r \n \t { } | \ ^ ' автоматически будут заэскейплены.
=======================================
| Query String - парсинг строки с параметрами из URL
=======================================
const querystring = require('querystring');
querystring.escape(str) // эскейпит строку символами с процентом
querystring.unescape(str) // анэскейпит (деколдирует) строку, содержащую символы с процентами
querystring.parse(str[, sep[, eq[, options]]]) // превращает строку с параметрами в объект
querystring.parse('foo=bar&abc=xyz&abc=123', '&', '=', {decodeURIComponent: querystring.unescape, maxKeys: 1000}) // {foo: 'bar', abc: ['xyz',
'123']}
querystring.stringify(obj[, sep[, eq[, options]]]) // преваращает объект с параметрами в строку
querystring.stringify({foo: 'bar', abc: ['xyz', '123']}, '&', '=', {encodeURIComponent: querystring.escape}) // 'foo=bar&abc=xyz&abc=123'
querystring.stringify({foo: 'bar', baz: ['qux', 'quux'], corge: ''}) // 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({foo: 'bar', baz: 'qux'}, ';', ':') // 'foo:bar;baz:qux'
=======================================
| Utilities - утилиты format, debuglog, deprecate, inspect
=======================================
// debuglog()
const util = require('util');
const debuglog = util.debuglog('foo');
debuglog('hello from foo [%d]', 123); // Если программа запущена с ключом NODE_DEBUG=foo, то в консоли будет выведено FOO 3245: hello
from foo [123] иначе функция не выведен ничего
// deprecate()
const util = require('util');
exports.puts = util.deprecate(function() {
for (var i = 0, len = arguments.length; i < len; ++i) {
process.stdout.write(arguments[i] + '\n');
}
}, 'util.puts: Use console.log instead'); // Выведет в консоли сообщение util.puts: Use console.log instead
// format()
Типы форматов:
%s - string
%d - number (integer и float).
%j - JSON
%% - символ '%'
util.format('%s:%s', 'foo'); // Returns 'foo:%s'
util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz'
util.format(1, 2, 3); // '1 2 3'
// inspect()
console.log(util.inspect(util, { showHidden: true, depth: null })); // выведет структуру всех свойст объекта
// Custom inspect()
const util = require('util');
const obj = { name: 'nate' };
obj.inspect = function(depth) {
return `{${this.name}}`;
};
util.inspect(obj); // "{nate}"
=======================================
| StringDecoder - декодирование объекта Buffer в строку
=======================================
new StringDecoder([encoding])
stringDecoder.end([buffer])
stringDecoder.write(buffer)
const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8');
const cent = Buffer.from([0xC2, 0xA2]);
console.log(decoder.write(cent));
const euro = Buffer.from([0xE2, 0x82, 0xAC]);
console.log(decoder.write(euro));
| Cheat sheet small - краткая подсказка
=======================================
npm init
npm install --save gulp
npm uninstall --save gulp
npm update
npm list
global
require
export
module.exports
assert()
console.log()
process.argv
process.stdout.write()
porcess.stderr.write()
porcess.stdin
process.exit()
process.stdout.clearLine()
process.stdout.cursorTo()
child_porcess.spawn()
child_process.exec()
var emeitter = new events.EventEmitter();
emeitter.on()
emeitter.once()
emeitter.addListener()
emeitter.removeListener()
emeitter.emit()
setTimeout()
setInterval()
setImmediate()
Buffer
__filename
__dirname
path
fs.writeFile()
fs.appendFile()
fs.readFile()
fs.rename()
fs.unlink()
fs.stat.isFile()
fs.stat.isDirectory()
fs.readdir()
fs.mkdir()
fs.rename()
fd.rmdir
fs.createReadStream()
fs.createWriteStream()
writeStream.write()
readStream.pipe()
url.parse()
url.format()
querystring.parse(
querystring.stringify()
querystring.escape()
querystring.unescape()
http.request()
http.createServer()
bodyParser()
os
debugger
=======================================
| Cheat sheet big - большая подсказка
=======================================
// NPM
npm init
npm install --save gulp
npm uninstall --save gulp
npm update
npm list
// Global, __dirname, __filename
console.log(global); // аналог window
console.log(__dirname); // абсолютный путь до папки из которой запущен данный файл
console.log(__filename); // абсолютный путь до данного файла
console.log(process.argv); // массив аргументов
// Process, stdout, stderr, stdin
process.stdout.write(`\n\n\n${__filename}\n\n\n`); // аналог console.log()
process.stderr.write(`\n\n\n${__dirname}\n\n\n`); // аналог console.error()
process.stdin.on("data", function (data) {
process.stdout.write(data.toString());
process.exit();
});
process.on("exit", function () {
process.stdout.write("Goodbye");
});
process.stdout.clearLine(); // очистить текущую строку выводы в окне терминала
process.stdout.cursorTo(0); // переместить курсор в окне терминала на позицию 0
// Дочерний процесс - выполнить команду для терминала - exec
var exec = require("child_process").exec; // выполнить команду для терминала
var command = "open http://www.goggle.com"; // команда для терминала
exec(command, function (error, stdout) {
if (error) {throw error;}
console.log("Done");
console.log(stdout);
});
// Дочерний процесс - запустить дочерний процесс - spawn
var spawnProcess = require("child_process").spawn;
var terminalCommand = "node";
var options = ["script-file.js", "say", "hi!"];
var childProcess = spawn(terminalCommand, options);
childProcess.stdout.on("data", function (data) {
console.log(data.toString());
});
childProcess.on("close", function () {
console.log("Done");
process.exit();
});
setTimeout(function(){
childProcess.stdin.write("stop"); // выполнить команду в консоли дочернего процесса
}, 5000);
// Модули - require, export, module.exports
var moduleFile = require("moduleFile"); // пути: ./ - текущая папка, ../ - внешняя папка, / - внутренняя папка
export var a = 1;
export function b () {}
module.exports = {a: a, b: b}; // аналог return из RequireJS
// События - on, once, emit, addListener, removeListener
var events = require("events");
var emitter = new events.EventEmitter();
emitter.on("say", function say (message) {});
emitter.once("say", function say (message) {});
emitter.addListener("say", function say (message) {});
emitter.removeListener("say", say);
emitter.emit("say", "Hello World");
// Работа с файлами - получение списка файлов, находящихся в папке - readdir
var fs = require("fs");
var files = readdirSync("./some/folder");
console.log(files);
readdir("./some/folder", function (error, files) {
if (error) {throw error;}
console.log(files);
});
// Работа с файлами - чтение содержимого файла - readFile
var fs = require("fs");
var fileContent = fs.readFileSync("./some/file.txt", "UTF-8"); // кодировку нужно указывать !!!
console.log(fileContent);
readFile("./some/file.txt", "UTF-8", function (error, fileContent) {
if (error) {throw error;}
console.log(fileContent);
});
// Работа с файлами - получение описания файла stat
var fs = require("fs");
var path = require("path");
fs.readdir("./libs", function (error, files) {
if (error) {throw error;}
files.forEach(function (fileName) {
var file = path.join(__dirname, "libs", fileName); // абсолютный путь до файла
var stats = fs.statSync(file);
if (stats.isFile()) {
fs.readFile(file, "UTF-8", function (error, fileContent) {
if (error) {throw error;}
console.log(fileContent);
});
} else if (stats.isDirectory()) {
console.log("It is directory");
}
});
});
// Работа с файлами - создание файла и запись в файл - writeFile
var fs = require("fs");
var fileContent = "Hello World";
fs.writeFileSync("sample.txt", fileContent);
console.log("Done");
fs.writeFile("sample.txt", fileContent, function (error) {
if (error) {throw error;}
console.log("Done");
});
fs.appendFile("sample.txt", "\nGoodbye");
// Работа с файлами - переименование и перемещение файлов в другую папку - rename
var fs = require("fs");
fs.renameSync("./lib/file-1.js", "./lib/file-2.js"); // переименование файла
console.log("Файл переименован");
fs.rename("./lib/file-1.js", "./file-1.js", function (error) { // перемещение файла в другую папку
if (error) {throw error;}
console.log("Файл пемемещен в другую папку");
});
// Работа с файлами - удаление файлов - unlink
var fs = require("fs");
try {
fs.unlinkSync("./lib/file-1.js"); // удаление файла
console.log("Done");
} catch (error) {
console.log(error);
}
fs.unlink("./lib/file-1.js", function (error) { // удаление файла
if (error) {throw error;}
console.log("Done");
});
// Работа с файлами - создание директорий - mkdir, exists
var fs = require("fs");
if (fs.existsSync("lib")) {
console.log("Directory lib already exists");
} else {
fs.mkdir("libs", function (error) {
if (error) {throw error;}
console.log("Directory created");
});
}
// Работа с файлами - переименование и перемещение папок в другую папку - rename
var fs = require("fs");
fs.renameSync("./assets/logs", "./logs"); // перемещение папки в другую папку
console.log("Done");
// Работа с файлами - удаление папки - rmdir - НЕЛЬЗЯ УДАЛИТЬ ПАПКУ, ЕСЛИ В НЕЙ ЕЩЕ ЕСТЬ ФАЙЛЫ! СНАЧАЛА НАДО УДАЛИТЬ ВСЕ ФАЙЛЫ!
var fs = require("fs");
var files = fs.readdirSync("./libs");
if (files.length > 0) {
files.forEach(function (fileName) {
fs.unlinkSync("./libs" + fileName);
});
}
fs.rmdir("./libs", function (error) {
if (error) {throw error;}
console.log("Done");
});
// Потоки - readable, writable, duplex = readable + writable
// Потоки - создание потока для чтения данных - createReadStream
var fs = require("fs");
var readStream = fs.createReadStream("./chat.log", "UTF-8"); // прочитать содержимое файла в потоке
var fileContent = "";
readStream.on("data", function (chunk) {
fileContent += chunk;
process.stdout.write(chunk);
});
readStream.on("end", function () {
console.log("Done");
});
// Потоки - создание потока для записи данных - createWriteStream
var fs = require("fs");
var writeSteam = fs.createWriteStream("./chat.log");
for (var i = 0; i < 1000; i++) {
writeStream.write(Math.random());
}
// HTTP - клиентский запрос - request
var http = require("http");
var fs = require("fs");
var options = {
hostname: "google.com",
post: 80
path: "/search/data",
method: "GET"
};
var request = http.request(options, function (response) {
response.setEncoding("UTF-8");
console.log(response.statusCode);
console.log(response.headers);
var responseBody = "";
response.on("data", function (chunk) {
responseBody += chunk;
});
response.on("end", function () {
fs.writeFile("some.html", responseBody, function (error) {
if (error) {throw error;}
console.log("File downloaded");
});
});
});
request.on("error", function () {
console.log("Error in request");
});
request.end(); // Послать запрос на сервер
// HTTP - создание сервера - createServer
var http = require("http");
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
response.write("<!DOCTYPE html>");
response.end(); // Завершить отправку ответа
});
server.listen("127.0.0.1:80"); // Создать сервер
// HTTP - обслуживание файлов - writeHead, write, end, url, method
var http = require("http");
var fs = require("fs");
var path = require("path");
var server = http.createServer(function (request, responce) {
console.log(respose.method);
if (requres.url === "/") {
fs.readFile("./public/index.html", "UTF-8", function (error, fileContent) {
if (error) {throw error;}
response.writeHead(200, {"Content-Type": "text/html"});
response.end(fileContent);
});
} else if (request.url.match(/.css$/)) {
var cssPath = path.join(__dirname, "public", request.url);
var readFileStream = fs.createReadStream(cssPath, "UTF-8"); // текстовые данные
response.writeHead(200, {"Content-Type": "text/css"});
readFileStream.on("data", function (chunk) {
response.write(chunk);
});
readFileStream.on("end", function () {
response.end();
});
// или можно так
// readFileStream.pipe(response); // автоматически ставит в конце response.end()
} else if (request.url.match(/.jpg$/)) {
var imagePath = path.join(__dirname, "public", request.url);
var readFileStream = fs.createReadStream(imagePath); // бинарные данные
response.writeHead(200, {"Content-Type": "image/jpeg"});
readFileStream.pipe(response);
} else {
response.writeHead(404, {"Content-Type": "text/plain"});
response.end("404 File Not Found");
}
console.log(request);
});
server.listen("127.0.0.1:80");
// HTTP - обслуживание JSON - writeHead, write, end, url, method
var http = require("http");
var data = require("./json-file");
var server = http.createServer(function (request, response) {
if (request.url === "/") {
response.writeHead(200, {"Content-Type": "text/json"});
response.end(JSON.stringify(data));
} else if (request.url === "/instock") {
listInStock(response);
} else if (requrest.url === "/onorder") {
listOnBackOrder(response);
} else {
response.writeHead(404, {"Content-Type": "text/plain");
response.end("404 File Not Found");
}
});
server.listen("127.0.0.1:80");
function listInStock (response) {
var inStock = data.filter(function (item) {
return item.available === "In stock";
});
response.writeHead(200, {"Content-Type": "text/json"});
reponse.end(JSON.stringify(inStock));
}
function listOnBackOrder (response) {
var onOrder = data.filter(function (item) {
return item.available === "On back order";
});
response.writeHead(200, {"Content-Type": "text/json"});
reponse.end(JSON.stringify(onOrder));
}
// HTTP - обслуживание GET, POST - writeHead, write, end, url, method
var http = require("http");
var fs = require("fs");
var server = http.createServer(function (request, response) {
if (request.method === "GET") {
response.writeHead(200, {"Content-Type": "text/html"});
var fileReadStream = fs.createReadStream("./public/form.html", "UTF-8");
fileReadStream.pipe(response);
} else if (request.method === "POST") {
var body = "";
request.on("data", function (chunk) {
body += chunk;
});
request.on("end", function () {
response.writeHead(200, {"Content-Type": "text/html"});
reponse.end(body);
});
}
});
server.listen("127.0.0.1:80");
// Express - сервер и прослойки middleware - app, use, get, post, delete, static, bodyParser
var express = require("express");
var app = express();
app.use(express.static("./public"));
app.use(epress.bodyParser({uploadDir: "./upload"}));
app.use(function (request, response, next) {
console.log(request.method);
console.log(request.url);
next();
});
app.get("/", function (request, response) {
response.json({one: 1, two: 2});
});
app.post("/form", function (request, response) {
response.end("<!DOCTYPE html>" + request.body);
});
app.delete("/delete/:id", function (request, response) {
response.end(request.params.id);
});
app.listen("127.0.0.1:80");
module.exports = app;
// WebSockets - стронняя библиотека WS для работы с WebSockets - WebSocketServer, send
var WebSocketServer = require("ws");
var wss = new WebSocketServer({port: 80});
wss.on("connection", function (webSocket) {
webSocket.on("message", function (message) {
if (message === "exit") {
webSocket.close();
} else {
wss.clients.forEach(function (client) {
client.send(message);
});
}
});
webSocket.send("Welcome to chat");
});
// Socket.IO - стронняя библиотека Socket.IO для работы с WebSockets - emit
var express = require("express");
var http = require("http");
var io = require("socket.io");
var app = express();
var server = http.createServer(app).listen("127.0.0.1:80");
io(server);
app.use(express.static("./public"));
io.on("connection", function (socket) {
socket.on("chat", function (message) {
socket.broadcast.emit("message", message);
});
socket.emit("message", "Welcome to chat");
});
=======================================
| Assertion Testing - ассерты для тестирования
=======================================
const assert = require('assert');
assert(false, 'it is false'); // throws: AssertionError: it is false
assert.ok(false, 'it is false'); // throws: AssertionError: it is false
assert.equal({a: {b: 1}}, {a: {b: 1}}); // throws: AssertionError: { a: { b: 1 } } == { a: { b: 1 } }
assert.strictEqual(1, '1'); // throws: AssertionError: 1 === '1'
assert.deepEqual({a: {b: 1}}, {a: {b: 2}}; // throws: AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } }
assert.deepStrictEqual({a: 1}, {a: '1'}); // throws: AssertionError: { a: 1 } deepStrictEqual { a: '1' }
assert.fail(1, 2, undefined, '>'); // throws: AssertionError: 1 > 2
assert.fail(1, 2, 'whoops', '>'); // throws: AssertionError: whoops
assert.notEqual(1, 1); // throws: AssertionError: 1 != 1
assert.notStrictEqual(1, 1); // throws: AssertionError: 1 != 1
assert.notDeepEqual({a: {b: 1}}, {a: {b: 1}}); // throws: AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } }
assert.notDeepStrictEqual({a: '1'}, {a: '1'}); // throws: AssertionError: { a: '1' } notDeepStrictEqual { a: '1' }
=======================================
| Buffer - буферы - массивы для двоичных данных
=======================================
const buf = Buffer.alloc(10); // <Buffer 00 00 00 00 00 00 00 00 00 00>
const buf = Buffer.alloc(10, 1); // <Buffer 01 01 01 01 01 01 01 01 01 01>
const buf = Buffer.from([1, 2, 3]); // <Buffer 01 02 03>
const buf = Buffer.from('test', 'utf8'); // <Buffer 74 65 73 74>
const buf = Buffer.from('hello world', 'ascii');
Варианты метода from:
- Buffer.from(array);
- Buffer.from(buffer);
- Buffer.from(arrayBuffer[, byteOffset [, length]]);
- Buffer.from(str[, encoding]);
const buf = Buffer.from([1, 2, 3]);
for (var b of buf) {
console.log(b);
}
// Prints:
// 1
// 2
// 3
console.log(buf.toString('hex')); // prints: 68656c6c6f20776f726c64
console.log(buf.toString('base64')); // prints: aGVsbG8gd29ybGQ=
Варианты кодировок:
- 'ascii'
- 'utf8'
- 'utf16le'
- 'ucs2'
- 'base64'
- 'binary'
- 'hex'
const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);
console.log(buf.length); // Prints: 16
const buf = Buffer.from([1, 2, 3]); // <Buffer 01 02 03>
buf[1] = 5; // <Buffer 01 05 03>
console.log(buf.compare(buf)); // Prints: 0
console.log(buf1.equals(buf2)); // Prints: true
buf1.copy(buf2, 8, 16, 20);
const buf = Buffer.allocUnsafe(10);
buf.fill('h');
console.log(buf.toString()); // Prints: hhhhhhhhhh
const buf = Buffer.from('this is a buffer');
buf.indexOf('this'); // returns 0
buf.indexOf('is'); // returns 2
buf.lastIndexOf('this'); // returns 0
buf.lastIndexOf('buffer'); // returns 17
buf.includes('this'); // returns true
const buf = Buffer.from('buffer');
for (var key of buf.keys()) {
console.log(key);
}
// prints:
// 0
// 1
// 2
// 3
// 4
// 5
Buffer.isBuffer(obj) // true или false
const buf = Buffer.alloc(1234);
console.log(buf.length); // Prints: 1234
const buf2 = buf1.slice(0, 3);
const buf = Buffer.alloc(3, 1); // <Buffer 01 01 01>
buf.toJSON(); // {type: 'Buffer', data: [1, 1, 1]}
const buf = Buffer.from('buffer');
for (var value of buf.values()) {
console.log(value);
}
// prints:
// 98
// 117
// 102
// 102
// 101
// 114
const buf = Buffer.allocUnsafe(256);
const len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); // Prints: 12 bytes: 1/2 + 1/4 = 3/4
const buf = Buffer.alloc(3, 1); // <Buffer 01 01 01>
buf.inspect(); // <Buffer 01 01 01>
buffer.INSPECT_MAX_BYTES; // Default: 50
=======================================
| Child Processes - работа с окном командной строки и запуск дополнительных дочерних процессов Node.js
=======================================
child_process.exec() - асинхронно запускает окно командной строки и выполняет внутри него команду, передавая stdout и stderr в callback
function когда выполнение команды завершится.
child_process.execFile() - такой же как child_process.exec() за исключением того, что команда выполняется напрямую без запуска окна
командной строки.
child_process.execSync() - синхронная версия child_process.exec(), блокирующая Node.js event loop.
child_process.execFileSync() - синхронная версия child_process.execFile(), блокирующая Node.js event loop.
child_process.fork() - запускает новый отдельный процесс Node.js и открывает канал для передачи сообщений между родительским процессом
Node.js и дочерним процессом Node.js.
child_process.spawn() - асинхронно запускает дочерний процесс Node.js, передавая stdout и stderr в callback function когда выполнение
команды завершится.
child_process.spawnSync() - синхронная версия child_process.spawn(), блокирующая Node.js event loop до завершения выполнения дочернего
процесса.
Достыпные Events:
- on('data, function () {})
- on('close', function () {})
- on('disconnect', function () {})
- on('error', function () {})
- on('exit', function () {})
- on('message', function () {})
Методы:
- child.send(message[, sendHandle[, options]][, callback])
- child.connected
- child.disconnect()
- child.kill([signal])
- child.pid
- child.stderr
- child.stdin
- child.stdio
- child.stdout
Примеры:
const spawn = require('child_process').spawn;
const listProcess = spawn('ls', ['-lh', '/usr']);
listProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
listProcess.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
listProcess.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
// Excute gulp task
var task = process.argv.slice(2).join(' ')
, command = 'node ./node_modules/gulp/bin/gulp.js ' + task
, childProcess = require('child_process').exec(command);
childProcess.stdout.on('data', function (data) {console.log(data);});
childProcess.stderr.on('data', function (data) {console.log(data);});
childProcess.on('data', function (code) {if (code === 0) {console.log('Done');} else {console.log('Exit code: ' + code);}});
// или
const exec = require('child_process').exec;
exec('cat *.js bad_file | wc -l', function (error, stdout, stderr) {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
// execFile
const execFile = require('child_process').execFile;
const child = execFile('node', ['--version'], function (error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
});
=======================================
| Console - console.log() - вывод сообщений на консоль
=======================================
console.log('hello world'); // Prints: hello world, to stdout
console.log('hello %s', 'world'); // Prints: hello world, to stdout
console.info([data][, ...]) - тоже самое, что и console.log([data][, ...])
console.dir(obj[, options]) // печатает свойства объекта
console.trace('Show me'); // Prints: (stack trace will vary based on where trace is called)
const code = 5;
console.error('error #%d', code); // Prints: error #5, to stderr
console.error('error', code); // Prints: error 5, to stderr
console.warn([data][, ...]) - тоже самое, что и console.error([data][, ...])
console.assert(true, 'does nothing'); // OK
console.assert(false, 'Whoops %s', 'didn\'t work'); // AssertionError: Whoops didn't work
console.time('100-elements');
for (var i = 0; i < 100; i++) {}
console.timeEnd('100-elements'); // prints 100-elements: 225.438ms
=======================================
| Debugger - запуск отладчика debugger; в браузере для отладки скрипта Node.js
=======================================
Описание команд:
Команды перехода по коду:
cont, c - продолжить выполнения кода
next, n - перейти к следующему шагу
step, s - войти внутрь функции
out, o - выйти из функции
pause - поставить выполнение кода на паузу, как при нажатии на кнопку паузы в Chrome Developer Tools
Команды для расстановки точек остановок в коде:
setBreakpoint(), sb() - установить breakpoint на текущую линию кода
setBreakpoint(line), sb(line) - установить breakpoint конкретную линию кода
setBreakpoint('fn()'), sb(...) - установить breakpoint первую строчку внутри тела функции
setBreakpoint('script.js', 1), sb(...) - установить breakpoint первую строчку файлы script.js
clearBreakpoint('script.js', 1), cb(...) - удалить breakpoint в файле script.js с линии 1
// myscript.js
x = 5;
setTimeout(() => {
debugger;
console.log('world');
}, 1000);
console.log('hello');
// запуск отладки скрипта
$ node debug myscript.js
< debugger listening on port 5858
connecting... ok
break in /home/indutny/Code/git/indutny/myscript.js:1
1 x = 5;
2 setTimeout(() => {
3 debugger;
debug> cont
< hello
break in /home/indutny/Code/git/indutny/myscript.js:3
1 x = 5;
2 setTimeout(() => {
3 debugger;
4 console.log('world');
5 }, 1000);
debug> next
break in /home/indutny/Code/git/indutny/myscript.js:4
2 setTimeout(() => {
3 debugger;
4 console.log('world');
5 }, 1000);
6 console.log('hello');
debug> repl
Press Ctrl + C to leave debug repl
> x
5
> 2+2
4
debug> next
< world
break in /home/indutny/Code/git/indutny/myscript.js:5
3 debugger;
4 console.log('world');
5 }, 1000);
6 console.log('hello');
7
debug> quit
=======================================
| Events - события addListener(), removeListener(), emit()
=======================================
emitter.addListener(eventName, listener) - тоже самое, что и emitter.on(eventName, listener) - добавить событие
emitter.prependListener() - добавить событие в самое начало списка имеющихся событий
emitter.once(eventName, listener) - добавить событие, которое будет удалено сразу после его вызова
emitter.prependOnceListener() - добавить событие в самое начало списка имеющихся событий, которое будет удалено сразу после его вызова
emitter.emit(eventName[, arg1][, arg2][, ...]) - синхронно вызвать функции привязанные к события в порядке их привязки с передачей в них
аргументов
emitter.removeListener(eventName) - удалить событие
emitter.removeAllListeners([eventName]) - удалить все события
emitter.eventNames() - вернуть массив существующих имен событий
emitter.listenerCount(eventName) - подсчитать число существующих событий
emitter.getMaxListeners() - получить предельно допустимое число возможных событий (по умолчанию 10)
emitter.setMaxListeners(n) - установить предельно допустимое число возможных событий
emitter.listeners(eventName) - получить массив с копией функций привязанных к событию
// Пример добавления событий
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function callback (a, b) {
console.log(a, b, this);
// Prints:
// a b MyEmitter {
// domain: null,
// _events: { event: [Function] },
// _eventsCount: 1,
// _maxListeners: undefined }
});
myEmitter.emit('event', 'a', 'b');
myEmitter.removeEvent('event', callback);
// метод on
const myEmitter = new MyEmitter();
var m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event'); // Prints: 1
myEmitter.emit('event'); // Prints: 2
// метод once
const myEmitter = new MyEmitter();
var m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event'); // Prints: 1
myEmitter.emit('event'); // Ignored
// Error event
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!')); // Throws and crashes Node.js
=======================================
| Stream - end, read, write, pause, resume, pipe, unpipe
=======================================
const stream = require('stream');
Types of Streams:
- Readable - fs.createReadStream()
- Writable - fs.createWriteStream()
- Duplex - net.Socket
- Transform
Readable
readable.read([size])
readable.pause()
readable.resume()
readable.isPaused()
readable.pipe(destination[, options])
readable.unpipe([destination])
readable.setEncoding(encoding)
readable.wrap(stream)
readable.unshift(chunk)
Readable Events
- 'close'
- 'data'
- 'end'
- 'error'
- 'readable'
Writable
writable.write(chunk[, encoding][, callback])
writable.end([chunk][, encoding][, callback])
writable.cork()
writable.uncork()
writable.setDefaultEncoding(encoding)
Writable Events
- 'close'
- 'drain'
- 'error'
- 'finish'
- 'pipe'
- 'unpipe'
=======================================
| File System - open, close, readFile, writeFile, appendFile unlink, stats, access, watch
=======================================
// Создать поток для чтения из файла
fs.createReadStream(path[, options])
// Создать поток для записи в файл
fs.createWriteStream(path[, options])
// Открыть файл
fs.open(path, flags[, mode], callback)
// Закрыть файл
fs.close(fd, callback)
// Прочитать файл
fs.read(fd, buffer, offset, length, position, callback)
// Асинхронно прочитать весь файл целиком
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
// Прочитать содержимое директории
fs.readdir(path[, options], callback)
// Добавление текста в конец файла
fs.appendFile('message.txt', 'data to append', (err) => {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
// Усечь файл
fs.ftruncate(fd, len, callback)
// Записать данные в файл или создать новый файл
fs.write(fd, buffer, offset, length[, position], callback)
fs.write(fd, data[, position[, encoding]], callback)
// Записать данные в файл и заменить его на новый, если он уже существует
fs.writeFile(file, data[, options], callback)
// Переименовать файл
fs.rename(oldPath, newPath, callback)
// Проверить существует ли файл - deprecated
fs.exists('/etc/passwd', (exists) => {
console.log(exists ? 'it\'s there' : 'no passwd!');
});
// Сведения о файлах
fs.stat()
fs.lstat()
fs.fstat()
stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink() (only valid with fs.lstat())
stats.isFIFO()
stats.isSocket()
// Изменение атрибутов файла
fs.chmod(path, mode, callback)
// Изменение владельца файла
fs.chown(path, uid, gid, callback)
// Изменения атрибутов файла
fs.constants.F_OK - файл видим для текущего процесса (значение по умолчанию)
fs.constants.R_OK - файл можешт быть прочитан текущим процессом
fs.constants.W_OK - файл можешт быть записан текущим процессом
fs.constants.X_OK - файл можешт быть выполнен текущим процессом
fs.access('/etc/passwd', fs.constants.R_OK | fs.constants.W_OK, (err) => {
console.log(err ? 'no access!' : 'can read/write');
});
// Отслеживание изменений файлов
fs.watch('./tmp', {encoding: 'buffer'}, (eventType, filename) => {
if (filename)
console.log(filename);
// Prints: <Buffer ...>
});
// Отслеживать изменения конкретного файла
fs.watchFile('message.text', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
// Скопировать файл
fs.link(srcpath, dstpath, callback)
// Асинхронная версия удаления файла
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('successfully deleted /tmp/hello');
});
// Синхронная версия удаления файла
const fs = require('fs');
fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');
// Создать директорию
fs.mkdir(path[, mode], callback)
// Удалить директорию
fs.rmdir(path, callback)
=======================================
| Path
=======================================
const path = require('path');
path.basename('/foo/bar/baz/asdf/quux.html') // returns 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', '.html') // returns 'quux'
path.win32..
path.posix..
path.delimiter
; for Windows
: for POSIX
path.sep
\ on Windows
/ on POSIX
// on POSIX:
'foo/bar/baz'.split(path.sep) // returns ['foo', 'bar', 'baz']
// on Windows:
'foo\\bar\\baz'.split(path.sep) // returns ['foo', 'bar', 'baz']
// on POSIX:
console.log(process.env.PATH) // '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'
process.env.PATH.split(path.delimiter) // returns ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
// on Windows:
console.log(process.env.PATH) // 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'
process.env.PATH.split(path.delimiter) // returns ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
path.dirname('/foo/bar/baz/asdf/quux') // returns '/foo/bar/baz/asdf'
path.extname('index.html') // returns '.html'
path.extname('index.coffee.md') // returns '.md'
path.extname('index.') // returns '.'
path.extname('index') // returns ''
path.extname('.index') // returns ''
path.format({dir: '/home/user/dir', base: 'file.txt'}); // returns '/home/user/dir/file.txt'
path.format({root: '/', base: 'file.txt'}); // returns '/file.txt'
path.format({root: '/', name: 'file', ext: '.txt'}); // returns '/file.txt'
path.format({base: 'file.txt'}); // returns 'file.txt'
path.format({root : "C:\\", dir : "C:\\path\\dir", base : "file.txt", ext : ".txt", name : "file"}); // returns 'C:\\path\\dir\\file.txt'
path.isAbsolute('/foo/bar') // true
path.isAbsolute('/baz/..') // true
path.isAbsolute('qux/') // false
path.isAbsolute('.') // false
path.isAbsolute('//server') // true
path.isAbsolute('C:/foo/..') // true
path.isAbsolute('bar\\baz') // false
path.isAbsolute('.') // false
ath.join('/foo', 'bar', 'baz/asdf', 'quux', '..') // returns '/foo/bar/baz/asdf'
path.join('foo', {}, 'bar') // throws TypeError: Arguments to path.join must be strings
path.normalize('/foo/bar//baz/asdf/quux/..') // returns '/foo/bar/baz/asdf'
path.normalize('C:\\temp\\\\foo\\bar\\..\\'); // returns 'C:\\temp\\foo\\'
// on POSIX:
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb') // returns '../../impl/bbb'
// on Windows:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb') // returns '..\\..\\impl\\bbb'
path.resolve('/foo/bar', './baz') // returns '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/') // returns '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif') // if the current working directory is /home/myself/node, this returns
'/home/myself/node/wwwroot/static_files/gif/image.gif'
// on POSIX:
┌───────────────────┬────────────┐
│ dir │ base │
├──────┬ ├─────┬──────┤
│ root │ │ name │ ext │
│ / home/user/dir / file .txt │
└──────┴───────────┴──────┴─────┘
path.parse('/home/user/dir/file.txt')
// returns
// {
// root : "/",
// dir : "/home/user/dir",
// base : "file.txt",
// ext : ".txt",
// name : "file"
// }
on Windows:
┌───────────── ──┬────────────┐
│ dir │ base │
├──────┬ ├──────┬─────┤
│ root │ │ name │ ext │
│ C:\ path\dir \ file .txt │
└──────┴──── ───┴──────┴─────┘
path.parse('C:\\path\\dir\\file.txt')
// returns
// {
// root : "C:\\",
// dir : "C:\\path\\dir",
// base : "file.txt",
// ext : ".txt",
// name : "file"
// }
=======================================
| Globals - __driname, __filename, global, Buffer, process, setTimeout, clearTimweout, console, module, exports, require
=======================================
console.log(__dirname); // /Users/mjr
console.log(__filename); // /Users/mjr/example.js
=======================================
| Modules - require, module, export, exports, name, id, parent, loaded
=======================================
require(X) from module at path Y
1. If X is a core module,
a. return the core module
b. STOP
2. If X begins with './' or '/' or '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.json is a file, parse X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
4. If X/index.node is a file, load X/index.node as binary addon. STOP
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
c. DIR = path join(PARTS[0 .. I] + "node_modules")
b. DIRS = DIRS + DIR
c. let I = I - 1
5. return DIRS
The module wrapper#
Before a module's code is executed, Node.js will wrap it with a function wrapper that looks like the following:
(function (exports, require, module, __filename, __dirname) {
// Your module code actually lives in here
});
module.filename
module.id
module.loaded
module.parent
module.require(id)
require.main === module
const circle = require('./circle.js');
console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);
// assigning to exports will not modify module, must use module.exports
module.exports = (width) => {
return {
area: () => width * width
};
}
=======================================
| OS - EOL, platform, type, cpus, homedir, tmpdir
=======================================
const os = require('os');
os.EOL
\n on POSIX
\r\n on Windows
os.endianness()
'BE' for big endian
'LE' for little endian.
os.arch() - тоже самое, что и process.arch
// 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', 'x64', 'x86'
os.platform() - тоже самое, что и process.platform
// 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', 'win32'
os.type() // 'Linux' on Linux, 'Darwin' on OS X, 'Windows_NT' on Windows
os.release()
os.constants
os.cpus()
os.freemem() - число доступных байт системной памяти
os.totalmem() - общее число байт системной памяти
os.homedir() - домашняя директория в операционной системе
os.tmpdir() - директория для временных файлов в операционной системе
os.loadavg()
os.uptime()
os.networkInterfaces()
{
address: '127.0.0.1',
netmask: '255.0.0.0',
family: 'IPv4',
mac: '00:00:00:00:00:00',
internal: true
}
OS Constants:
- Signal Constants
- Error Constants
- POSIX Error Constants
- Windows Specific Error Constants
- libuv Constants
=======================================
| Process - argv, nextTick, exit, abort, stdin, stdout, stderr, chdir, cwd, env, hrtime
=======================================
process - это глобальный объект, экземляр Event Emitter, предоставляющий информацию и контролирующий текущий процесс работы Node.js
process.stdin
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write(`data: ${chunk}`);
}
});
process.stdin.on('end', () => {
process.stdout.write('end');
});
process.stdout
console.log = (msg) => {
process.stdout.write(`${msg}\n`);
};
process.stderr
process.nextTick(callback[, arg][, ...])
console.log('start');
process.nextTick(() => {
console.log('nextTick callback');
});
console.log('scheduled');
// Output:
// start
// scheduled
// nextTick callback
process.exit(1)
if (someConditionNotMet()) {
printUsageToStdout();
process.exit(1);
}
process.exitCode
process.kill(pid[, signal])
process.kill(process.pid, 'SIGHUP');
process.getegid()
if (process.getegid) {
console.log(`Current gid: ${process.getegid()}`);
}
process.geteuid()
process.getgid()
process.pid
process.title
process.abort()
process.argv
$ node process-2.js one two=three four
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`);
});
$ node --harmony script.js --version
['/usr/local/bin/node', 'script.js', '--version']
process.execArgv
$ node --harmony script.js --version
['--harmony']
process.execPath // /usr/local/bin/node
process.stdin.resume();
process.chdir(directory)
process.cwd()
console.log(`Current directory: ${process.cwd()}`);
process.chdir('/tmp');
console.log(`Starting directory: ${process.cwd()}`);
try {
process.chdir('/tmp');
console.log(`New directory: ${process.cwd()}`);
}
catch (err) {
console.log(`chdir: ${err}`);
}
process.hrtime([time])
var time = process.hrtime(); // [ 1800216, 25 ]
process.uptime()
process.versions
{
http_parser: '2.3.0',
node: '1.1.1',
v8: '4.1.0.14',
uv: '1.3.0',
zlib: '1.2.8',
ares: '1.10.0-DEV',
modules: '43',
icu: '55.1',
openssl: '1.0.1k'
}
process.config
process.connected
process.disconnect()
process.arch
process.platform
process.cpuUsage([previousValue])
const startUsage = process.cpuUsage(); // { user: 38579, system: 6986 }
process.release
process.env
{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}
process.env.foo = 'bar';
console.log(process.env.foo);
process.env.test = null;
console.log(process.env.test); // => 'null'
process.env.test = undefined;
console.log(process.env.test); // => 'undefined'
process.env.TEST = 1;
delete process.env.TEST;
console.log(process.env.TEST); // => undefined
process.mainModule
process.memoryUsage()
process.send(message[, sendHandle[, options]][, callback])
process.on('exit', (code) => {
console.log(`About to exit with code: ${code}`);
});
process.on('beforeExit', function () {});
process.on('disconnect', function () {});
process.on('message', function () {});
process.on('rejectionHandled', function () {});
const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, p) => {
unhandledRejections.set(p, reason);
});
process.on('rejectionHandled', (p) => {
unhandledRejections.delete(p);
});
process.on('uncaughtException', function () {});
process.on('uncaughtException', (err) => {
fs.writeSync(1, `Caught exception: ${err}`);
});
process.on('warning', function () {});
process.on('warning', (warning) => {
console.warn(warning.name); // Print the warning name
console.warn(warning.message); // Print the warning message
console.warn(warning.stack); // Print the stack trace
});
process.emitWarning('Something happened!'); // Prints: (node 12345) Warning: Something happened!
process.emitWarning('This API is deprecated', 'DeprecationWarning');
Signal Events
process.on('SIGINT', () => {
console.log('Received SIGINT. Press Control-D to exit.');
});
=======================================
| HTTP - request, createServer, request, response, writeHead, write, end, setHeader, getHeader, removeHeader
=======================================
http.request(options[, callback])
http.createClient([port][, host])
http.createServer([requestListener])
http.globalAgent
http.get(options[, callback])
http.METHODS
http.STATUS_CODES
http.Agent
new Agent([options])
agent.createConnection(options[, callback])
agent.destroy()
agent.freeSockets
agent.getName(options)
agent.maxFreeSockets
agent.maxSockets
agent.requests
agent.sockets
http.ClientRequest
on('abort', function(){})
on('aborted', function(){})
on('checkExpectation', function(){})
on('connect', function(){})
on('continue', function(){})
on('response', function(){})
on('socket', function(){})
on('upgrade', function(){})
request.write(chunk[, encoding][, callback])
request.end([data][, encoding][, callback])
request.abort()
request.flushHeaders()
request.setNoDelay([noDelay])
request.setSocketKeepAlive([enable][, initialDelay])
request.setTimeout(timeout[, callback])
http.Server
on('checkContinue', function(){})
on('clientError', function(){})
on('close', function(){})
on('connect', function(){})
on('connection', function(){})
on('request', function(){})
on('upgrade', function(){})
server.listen(handle[, callback])
server.listen(path[, callback])
server.listen(port[, hostname][, backlog][, callback])
server.listening
server.close([callback])
server.maxHeadersCount
server.setTimeout(msecs, callback)
server.timeout
http.ServerResponse
on('close', function(){})
on('finish', function(){})
response.writeHead(statusCode[, statusMessage][, headers])
response.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/plain' });
response.write(chunk[, encoding][, callback])
response.end([data][, encoding][, callback])
response.setHeader(name, value)
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
response.getHeader(name)
var contentType = response.getHeader('content-type');
response.removeHeader(name)
response.removeHeader('Content-Encoding');
response.headersSent
response.setTimeout(msecs, callback)
response.statusCode
response.statusCode = 404;
response.statusMessage
response.statusMessage = 'Not found';
response.addTrailers(headers)
response.finished
response.sendDate
response.writeContinue()
http.IncomingMessage
on('aborted', function(){})
on('close', function(){})
message.headers
message.rawHeaders
message.setTimeout(msecs, callback)
message.statusCode
message.httpVersion
message.destroy([error])
message.method
message.rawTrailers
message.statusMessage
message.socket
message.trailers
message.url
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
var proxy = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
var srvUrl = url.parse(`http://${req.url}`);
var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {
// make a request to a tunneling proxy
var options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
var req = http.request(options);
req.end();
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
// ------------------------------------
const http = require('http');
// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', (req, socket, head) => {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n');
socket.pipe(socket); // echo back
});
// now that server is running
srv.listen(1337, '127.0.0.1', () => {
// make a request
var options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
req.on('upgrade', (res, socket, upgradeHead) => {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
// ----------------------------------------
const http = require('http');
const server = http.createServer((req, res) => {
res.end();
});
server.on('clientError', (err, socket) => {
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.listen(8000);
// ---------------------------------------
const server = http.createServer((req,res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
});
// -------------------------------------------------------
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
=======================================
| HTTPS -
=======================================
https.request(options, callback)
https.createServer(options[, requestListener])
https.Agent
https.Server
server.setTimeout(msecs, callback)
server.timeout
server.close([callback])
server.listen(handle[, callback])
server.listen(path[, callback])
server.listen(port[, host][, backlog][, callback])
https.get(options, callback)
https.globalAgent
// ---------------------------------------------
// curl -k https://localhost:8000/
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
// ---------------------------------------------
const https = require('https');
const fs = require('fs');
const options = {
pfx: fs.readFileSync('server.pfx')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
// ---------------------------------------------
const https = require('https');
https.get('https://encrypted.google.com/', (res) => {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
}).on('error', (e) => {
console.error(e);
});
// ---------------------------------------------
const https = require('https');
var options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET'
};
var req = https.request(options, (res) => {
console.log('statusCode: ', res.statusCode);
console.log('headers: ', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.end();
req.on('error', (e) => {
console.error(e);
});
// ---------------------------------------------
var options = {
hostname: 'encrypted.google.com',
port: 443,
path: '/',
method: 'GET',
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
options.agent = new https.Agent(options);
var req = https.request(options, (res) => {
...
});
=======================================
| Timers - setTimeout, setInterval, setImmediate, ref, unref
=======================================
var timeout = setTimeout(function(){}, 5000[, ...arg])
clearTimeout(timeout)
var interval = setInterval(function(){}, 5000[, ...arg])
clearInterval(interval )
var immediate = setImmediate(function(){}[, ...arg])
clearImmediate(immediate)
timeout.ref()
timeout.unref()
=======================================
| URL - парсинг урлов
=======================================
http://user:pass@host.com:8080/p/a/t/h?query=string#hash
┌───────────────────────────────────────────────────────────┐
│ href │
├───── ─┬┬─────── ┬─────────────┬───────────────────┬──────┤
│ protocol ││ auth │ host │ path │ hash │
│ ││ ├─────────────┼───── ───┬──────────┤ │
│ ││ │ hostname │ port │ pathname │ search │ │
│ ││ │ │ │ ├┬──────── ─┤ │
│ ││ │ │ │ │ │ query │ │
│ http: // user:pass @ host.com : 8080 /p/a/t/h ? query=string #hash │
│ ││ │ │ │ │ │ │ │
└───────┴┴─── ────┴────────┴────┴────── ─┴┴──────────┴─────┘
const url = require('url');
urlObject.href // 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
urlObject.protocol // 'http:'
urlObject.slashes // true
urlObject.host // 'host.com:8080'
urlObject.auth // 'user:pass
urlObject.hostname // 'host.com'
urlObject.port // '8080'
urlObject.pathname // '/p/a/t/h'
urlObject.search // ?query=string'
urlObject.path // '/p/a/t/h?query=string'
urlObject.query // 'query=string' или {'query': 'string'}
urlObject.hash '#hash'
url.format(urlObject) // возвращает отформатированную строку в адресом
url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) // берет строку с адресом и превращает её в объект URL object
url.resolve(from, to) // соединяет адрес страницы с адресом сайта
url.resolve('/one/two/three', 'four') // '/one/two/four'
url.resolve('http://example.com/', '/one') // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'
Пробелы и знаки < > " ` \r \n \t { } | \ ^ ' автоматически будут заэскейплены.
=======================================
| Query String - парсинг строки с параметрами из URL
=======================================
const querystring = require('querystring');
querystring.escape(str) // эскейпит строку символами с процентом
querystring.unescape(str) // анэскейпит (деколдирует) строку, содержащую символы с процентами
querystring.parse(str[, sep[, eq[, options]]]) // превращает строку с параметрами в объект
querystring.parse('foo=bar&abc=xyz&abc=123', '&', '=', {decodeURIComponent: querystring.unescape, maxKeys: 1000}) // {foo: 'bar', abc: ['xyz',
'123']}
querystring.stringify(obj[, sep[, eq[, options]]]) // преваращает объект с параметрами в строку
querystring.stringify({foo: 'bar', abc: ['xyz', '123']}, '&', '=', {encodeURIComponent: querystring.escape}) // 'foo=bar&abc=xyz&abc=123'
querystring.stringify({foo: 'bar', baz: ['qux', 'quux'], corge: ''}) // 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({foo: 'bar', baz: 'qux'}, ';', ':') // 'foo:bar;baz:qux'
=======================================
| Utilities - утилиты format, debuglog, deprecate, inspect
=======================================
// debuglog()
const util = require('util');
const debuglog = util.debuglog('foo');
debuglog('hello from foo [%d]', 123); // Если программа запущена с ключом NODE_DEBUG=foo, то в консоли будет выведено FOO 3245: hello
from foo [123] иначе функция не выведен ничего
// deprecate()
const util = require('util');
exports.puts = util.deprecate(function() {
for (var i = 0, len = arguments.length; i < len; ++i) {
process.stdout.write(arguments[i] + '\n');
}
}, 'util.puts: Use console.log instead'); // Выведет в консоли сообщение util.puts: Use console.log instead
// format()
Типы форматов:
%s - string
%d - number (integer и float).
%j - JSON
%% - символ '%'
util.format('%s:%s', 'foo'); // Returns 'foo:%s'
util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz'
util.format(1, 2, 3); // '1 2 3'
// inspect()
console.log(util.inspect(util, { showHidden: true, depth: null })); // выведет структуру всех свойст объекта
// Custom inspect()
const util = require('util');
const obj = { name: 'nate' };
obj.inspect = function(depth) {
return `{${this.name}}`;
};
util.inspect(obj); // "{nate}"
=======================================
| StringDecoder - декодирование объекта Buffer в строку
=======================================
new StringDecoder([encoding])
stringDecoder.end([buffer])
stringDecoder.write(buffer)
const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8');
const cent = Buffer.from([0xC2, 0xA2]);
console.log(decoder.write(cent));
const euro = Buffer.from([0xE2, 0x82, 0xAC]);
console.log(decoder.write(euro));
Подписаться на:
Сообщения (Atom)