{"id":222261,"date":"2014-05-13T22:53:03","date_gmt":"2014-05-13T18:53:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=222261"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=222261","title":{"rendered":"<span class=\"post_title\">\u041a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 CommonJS \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/383\/9b2\/f05\/3839b2f05fce04cfa7602d5375950e82.png\" align=\"right\"\/>  <\/p>\n<h4>\u041e \u0447\u0451\u043c \u0440\u0435\u0447\u044c?<\/h4>\n<p>  \u041e JS \u043c\u043e\u0434\u0443\u043b\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u041e\u0431 \u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445. \u041c\u0435\u043d\u044c\u0448\u0435 \u0442\u0435\u043e\u0440\u0438\u0438, \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u0443\u0440\u0441\u0430 \u043c\u043e\u043b\u043e\u0434\u043e\u0433\u043e \u0431\u043e\u0439\u0446\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0438 \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0431\u0430\u0437\u0435 Node.JS: ToDo-\u043b\u0438\u0441\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442:  <\/p>\n<ol>\n<li>\u00ab\u0417\u0430\u0432\u0435\u0441\u0442\u0438\u00bb \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 Express;<\/li>\n<li>\u041d\u0430\u0443\u0447\u0438\u0442\u044c \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438;<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c;<\/li>\n<li>\u0422\u0430\u043a\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c ToDo-\u043b\u0438\u0441\u0442;<\/li>\n<li>\u041e\u0441\u043c\u044b\u0441\u043b\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/li>\n<\/ol>\n<p>  <a name=\"habracut\"><\/a>  <\/p>\n<h4>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e<\/h4>\n<p>  \u0421\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u0441\u0443\u0442\u0438 \u0432\u0441\u0435\u0439 \u0437\u0430\u0442\u0435\u0438 \u0438 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0444\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<ol>\n<li>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430;<\/li>\n<li>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c ToDo-\u043b\u0438\u0441\u0442\u043e\u043c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u041f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f, \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u0438\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u2014 \u0441\u043e\u0437\u0434\u0430\u0442\u044c\u0441\u044f \u043d\u043e\u0432\u044b\u0439;<\/li>\n<li>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043f\u0443\u043d\u043a\u0442\u044b \u0432 \u0441\u043f\u0438\u0441\u043e\u043a;<\/li>\n<li>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439.<\/li>\n<\/ol>\n<h4>\u0414\u0435\u043b\u0430\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441<\/h4>\n<p>  \u0411\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"http:\/\/expressjs.com\/guide.html#executable\">\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 Express<\/a>. \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438:  <\/p>\n<pre><code>. \u251c\u2500\u2500 bin \u251c\u2500\u2500 client                  \/\/ \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u251c\u2500\u2500 modules                 \/\/ \u0430 \u0437\u0434\u0435\u0441\u044c, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0430\u043c\u0438 CommonJS \u043c\u043e\u0434\u0443\u043b\u0438 \u251c\u2500\u2500 public \u2502\u00a0\u00a0 \u2514\u2500\u2500 stylesheets \u251c\u2500\u2500 routes \u2514\u2500\u2500 views  <\/code><\/pre>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438\u0437 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u2014 Point, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u0443\u043d\u043a\u0442\u0430 ToDo-\u043b\u0438\u0441\u0442\u0430:  <\/p>\n<pre><code class=\"javascript\">\/\/ modules\/Point\/Point.js  \/**  * \u041f\u0443\u043d\u043a\u0442 \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u0435\u043b  * @param {Object} params  * @param {String} params.description  * @param {String} [params.id]  * @param {Boolean} [params.isChecked]  * @constructor  *\/ function Point(params) {     if (!params.description) {         throw 'Invalid argument';     }      this._id = params.id;     this._description = params.description;     this._isChecked = Boolean(params.isChecked); }  Point.prototype.toJSON = function () {     return {         id: this._id,         description: this._description,         isChecked: this._isChecked     }; } <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/**  * @param {String} id  *\/ Point.prototype.setId = function (id) {     if (!id) {         throw 'Invalid argument';     }     this._id = id; }  \/**  * @returns {String}  *\/ Point.prototype.getId = function () {     return this._id; }  Point.prototype.check = function () {     this._isChecked = true; }  Point.prototype.uncheck = function () {     this._isChecked = false; }  \/**  * @returns {Boolean}  *\/ Point.prototype.getIsChecked = function () {     return this._isChecked; }  \/**  * @returns {String}  *\/ Point.prototype.getDescription = function () {     return this._description; }  module.exports = Point; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0417\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u042d\u0442\u043e \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043c\u044b \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"javascript\">\/\/ routes\/index.js  var express = require('express'); var router = express.Router();  \/* GET home page. *\/ router.get('\/', function (req, res) {     var Point = require('..\/modules\/Point');     var newPoint = new Point({             description: 'Do something'         });      console.log('My new point:', newPoint); });  module.exports = router; <\/code><\/pre>\n<p>  \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 CommonJS \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f middleware \u0434\u043b\u044f Express <a href=\"https:\/\/github.com\/ForbesLindesay\/browserify-middleware\">browserify-middleware<\/a>:  <\/p>\n<pre><code class=\"javascript\">\/\/ app.js  \/\/ ... var browserify = require('browserify-middleware');  app.use('\/client', browserify('.\/client')); \/\/ ... <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043e\u0434, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:  <\/p>\n<pre><code class=\"javascript\">\/\/ client\/todo.js  var console = require('console'); \/\/ \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442 `node_modules\/browserify\/node_modules\/console-browserify`  var Point = require('..\/modules\/Point'); <\/code><\/pre>\n<p>  Browserify \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043d\u043e\u0434\u043e\u0432\u0441\u043a\u0438\u0439 <a href=\"http:\/\/nodejs.org\/api\/modules.html#modules_all_together\">\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439<\/a>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <a href=\"http:\/\/nodejs.org\/api\/modules.html#modules_all_together\">\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 core \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a<\/a>. \u041e\u0431 \u044d\u0442\u043e\u043c \u0438 \u0431\u0435\u0437 \u0442\u043e\u0433\u043e \u043c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043a\u0430\u0436\u0443 \u043b\u0438\u0448\u044c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043a\u0440\u0438\u043f\u0442, \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <i>\/client\/todo.js<\/i> \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. <\/p>\n<h4>\u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u043c\u043e\u0434\u0443\u043b\u044f\u0445<\/h4>\n<p>  \u0412 \u0441\u0432\u043e\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0435 \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439:<\/p>\n<p>  <b>\u0423\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438<\/b><br \/>  \u0421 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u0442 \u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0430\u0435\u0442 \u043a\u043e\u0434. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u043c\u0438\u0441\u043e\u0432 <a href=\"https:\/\/github.com\/dfilatov\/vow\">Vow<\/a>, <a href=\"http:\/\/lodash.com\/\">lodash<\/a>, console. \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u0432\u043e\u0451\u043c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u043d\u043e \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 (CommonJS, AMD).<\/p>\n<p>  <b>\u041c\u043e\u0434\u0443\u043b\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/b><br \/>  \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438. \u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d \u043e\u0434\u0438\u043d \u0442\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u2014 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 Point, \u0432\u0441\u043a\u043e\u0440\u0435 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c list, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043d\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 (addPoint, getPoints, checkPoint) \u0438 \u043c\u043e\u0434\u0443\u043b\u044c user, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438.<\/p>\n<p>  \u0422\u0430\u043a\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u043c\u0438, \u0442\u0430\u043a \u0438 \u0438\u043c\u0435\u0442\u044c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041d\u043e \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e \u043c\u043e\u0434\u0443\u043b\u0435\u0439.<\/p>\n<p>  <b>DAL \u043c\u043e\u0434\u0443\u043b\u0438 (Data Access Layer)<\/b><br \/>  \u042d\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u0438, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u0438\u0437 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438 \u0438\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 (\u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438) \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u0414\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u044d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c localStorage, sessionStorage, cookies, \u0432\u043d\u0435\u0448\u043d\u0435\u0435 API. \u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432\u044b\u0431\u043e\u0440 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435: \u0446\u0435\u043b\u0430\u044f \u0432\u0435\u0440\u0435\u043d\u0438\u0446\u0430 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445, \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438, \u043e\u043f\u044f\u0442\u044c \u0436\u0435, \u043d\u0435\u043a\u043e\u0435 \u0432\u043d\u0435\u0448\u043d\u0435\u0435 API.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0441 DAL, \u0442\u043e DAL-\u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u0443\u044e \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u0435\u0434\u0438\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c. \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/github.com\/substack\/node-browserify#browser-field\">\u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0444\u0438\u0447\u0443 browserify<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <i>browser<\/i> \u0432 package.json \u043c\u043e\u0434\u0443\u043b\u044f. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 DAL-\u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0440\u0435\u0434\u044b \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:  <\/p>\n<pre><code class=\"javascript\">{     &quot;name&quot; : &quot;dal&quot;,     &quot;main&quot; : &quot;.\/node.js&quot;,    \/\/ \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435     &quot;browser&quot;: &quot;.\/browser.js&quot;    \/\/ \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d browserify \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 } <\/code><\/pre>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u0438<\/h4>\n<p>  \u041a\u0430\u043a\u0438\u0435 \u0436\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438? \u041f\u0443\u0441\u0442\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u0438\u0442 memcache, \u0432 \u043d\u0451\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0448\u0438 ToDo-\u0441\u043f\u0438\u0441\u043a\u0438. \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 sessionStorage \u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0430 DAL \u0443\u0440\u043e\u0432\u043d\u0435 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 sessionStorage \u0438 <a href=\"https:\/\/github.com\/elbart\/node-memcache\">memcache<\/a> (\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 Express).  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/dal\/browser\/sessionStorage.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">module.exports.set = function () {     sessionStorage.setItem.apply(sessionStorage, arguments); }  module.exports.get = function () {     return sessionStorage.getItem.apply(sessionStorage, arguments); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/dal\/node\/memcache.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var vow = require('vow'); var _ = require('lodash');  var memcache = require('memcache'); var client = new memcache.Client(21201, 'localhost');  var clientDefer = new vow.Promise(function(resolve, reject) {     client         .on('connect', resolve)         .on('close', reject)         .on('timeout', reject)         .on('error', reject)         .connect(); });  \/**  * \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a Memcache  * @see {@link https:\/\/github.com\/elbart\/node-memcache#usage}  * @param {String} clientMethod  * @param {String} key  * @param {*} [value]  * @returns {vow.Promise} resolve with {String}  *\/ function request(clientMethod, key, value) {     var requestParams = [key];      if (!_.isUndefined(value)) {         requestParams.push(value);     }      return new vow.Promise(function (resolve, reject) {         requestParams.push(function (err, data) {             if (err) {                 reject(err);             } else {                 resolve(data);             }         });          clientDefer.then(function () {             client[clientMethod].apply(client, requestParams);         }, reject);     }); }  \/**  * \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u043b\u044e\u0447\u0430  * @param {String} key  * @param {*} value  * @returns {vow.Promise}  *\/ module.exports.set = function (key, value) {     return request('set', key, value); }  \/**  * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0443  * @param {String } key  * @returns {vow.Promise} resolve with {String}  *\/ module.exports.get = function (key) {     return request('get', key); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 User, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c <i>getId<\/i>:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/user\/dal\/browser.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var storage = require('..\/..\/dal\/browser\/sessionStorage');  var key = 'todo_user_id';  \/**  * \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 id  * @returns {String}  *\/ function makeId() {     var text = &quot;&quot;;     var possible = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&quot;;     var i;      for (i = 0; i &lt; 10; i++) {         text += possible.charAt(Math.floor(Math.random() * possible.length));     }      return text; }  module.exports = {      \/**      * @returns {String}      *\/     getId: function () {         var userId = storage.get(key);          if (!userId) {             userId = makeId();             storage.set(key, userId);         }          return userId;     }  }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/user\/dal\/node.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var app = require('..\/..\/..\/app');  module.exports = {      \/**      * @returns {String}      *\/     getId: function () {         return app.get('userId'); \/\/ \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u043d\u0435\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e middleware     }  }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/user\/dal\/package.json<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">{     &quot;name&quot; : &quot;dal&quot;,     &quot;main&quot; : &quot;.\/node.js&quot;,     &quot;browser&quot;: &quot;.\/browser.js&quot; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ modules\/user\/user.js  var dal = require('.\/dal'); \/\/ \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d .\/dal\/browser.js, \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 - .\/dal\/node.js   function User() { }  \/**  * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0435\u0441\u0441\u0438\u0438  * @returns {String}  *\/ User.prototype.getId = function () {     return dal.getId(); }  module.exports = new User(); <\/code><\/pre>\n<p>  \u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043c\u044b \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 REST, \u0447\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442 \u043d\u0430\u0441 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 DAL-\u0443\u0440\u043e\u0432\u043d\u0435 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/dal\/browser\/rest.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var vow = require('vow'); var _ = require('lodash');  \/**  * \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a REST API  * @param {String} moduleName - \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c  * @param {String} methodName - \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043c\u0435\u0442\u043e\u0434  * @param {Object} params - \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430  * @param {String} method - \u0442\u0438\u043f \u0437\u0430\u043f\u0440\u043e\u0441\u0430  * @returns {vow.Promise} resolve with {Object} xhr.response  *\/ module.exports.request = function (moduleName, methodName, params, method) {     var url = '\/api\/' + moduleName + '\/' + methodName + '\/?',         paramsData = null;      if (_.isObject(params)) {         paramsData = _.map(params, function (param, paramName) {             return paramName + '=' + encodeURIComponent(param);         }).join('&');     }      if (method !== 'POST' && paramsData) {         url += paramsData;         paramsData = null;     }      return new vow.Promise(function (resolve, reject) {         var xhr = new XMLHttpRequest();          xhr.open(method, url);         xhr.setRequestHeader('Content-Type', 'application\/x-www-form-urlencoded');         xhr.responseType = 'json';         xhr.onload = function() {             if(xhr.status === 200) {                 resolve(xhr.response);             } else {                 reject(xhr.response || xhr.statusText);             }         };          xhr.send(paramsData);     }); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u043e\u0443\u0442\u0435\u0440\u0430 \u0434\u043b\u044f Express, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0438\u043c\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438:  <\/p>\n<pre><code class=\"javascript\">\/\/ routes\/api.js \/\/ ... router.use('\/:module\/:method', function (req, res) {     var module = require('..\/modules\/' + req.params.module),         method = module[req.params.method];      if (!method) {         res.send(405);         return;     }      method.apply(module, req.apiParams)         .then(function (data) {             res.json(data);         }, function (err) {             res.send(400, JSON.stringify(err));         }); }); \/\/ ... <\/code><\/pre>\n<p>  \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 API \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:  <\/p>\n<ol>\n<li>GET, \/list\/getPoints \u2013 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u043b \u0432 ToDo-\u043b\u0438\u0441\u0442\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f;<\/li>\n<li>POST, \/list\/addPoint \u2013 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u0432 ToDo-\u043b\u0438\u0441\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f;<\/li>\n<li>POST, \/list\/checkPoint \u2013 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u0443\u043d\u043a\u0442 \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u044b\u0439;<\/li>\n<\/ol>\n<p>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0432\u043e\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0440\u043e\u0443\u0442\u0435\u0440 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u0438: \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043c\u043e\u0434\u0443\u043b\u044e:  <\/p>\n<pre><code class=\"javascript\">router.post('\/list\/addPoint', function (req, res, next) {     var Point = require('..\/modules\/Point'),         point;      req.apiParams = [];      try {         point = new Point(JSON.parse(req.param('point')));         req.apiParams.push(point);     } catch (e) {}      next(); }); <\/code><\/pre>\n<p>  \u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 list:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/list\/dal\/browser.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var _ = require('lodash');  var rest = require('..\/..\/dal\/browser\/rest');  var Point = require('..\/..\/Point');  module.exports = {      \/**      * @param {User} user      * @returns {vow.Promise} resolve with {Point[]}      *\/     getPoints: function (user) {         return rest.request('list', 'getPoints', {userId: user.getId()}, 'GET')             .then(function (points) {                 return _.map(points, function (point) {                     return new Point(point);                 });             });     },      \/**      * @param {User} user      * @param {Point} point      * @returns {vow.Promise} resolve with {Point}      *\/     addPoint: function (user, point) {         var requestParams = {             userId: user.getId(),             point: JSON.stringify(point)         };          return rest.request('list', 'addPoint', requestParams, 'POST')             .then(function (point) {                 return new Point(point);             });     },      \/**      * @param {User} user      * @param {Point} point      * @returns {vow.Promise}      *\/     checkPoint: function (user, point) {         var requestParams = {             userId: user.getId(),             pointId: point.getId()         };          return rest.request('list', 'checkPoint', requestParams, 'POST');     }  }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/list\/dal\/node.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">var _ = require('lodash');  var memcache = require('..\/..\/dal\/node\/memcache');  var Point = require('..\/..\/Point');  \/**  * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u044e\u0447 \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f  * @param {User} user  * @returns {String}  *\/ function getListKey(user) {     return 'list_' + user.getId(); }  module.exports = {      \/**      * @param {User} user      * @returns {vow.Promise} resolve with {Point[]}      *\/     getPoints: function (user) {         return memcache.get(getListKey(user))             .then(function (points) {                 if (points) {                     try {                         points = _.map(JSON.parse(points), function (point) {                             return new Point(point);                         });                     } catch (e) {                         points = [];                     }                 } else {                     points = [];                 }                 return points;             });     },      \/**      * @param {User} user      * @param {Point} point      * @returns {vow.Promise} resolve with {Point}      *\/     addPoint: function (user, point) {         return this.getPoints(user)             .then(function (points) {                 point.setId('point_' + (new Date().getTime()));                 points.push(point);                  return memcache.set(getListKey(user), JSON.stringify(points))                     .then(function () {                         return point;                     });             });     },      \/**      * @param {User} user      * @param {Point} point      * @returns {vow.Promise}      *\/     checkPoint: function (user, point) {         return this.getPoints(user)             .then(function (points) {                 var p = _.find(points, function (p) {                     return p.getId() === point.getId();                 });                  if (!p) {                     throw 'Point not found';                 }                  p.check();                 return memcache.set(getListKey(user), JSON.stringify(points));             });     }  }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">modules\/list\/dal\/package.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">{     &quot;name&quot; : &quot;dal&quot;,     &quot;main&quot; : &quot;.\/node.js&quot;,     &quot;browser&quot;: &quot;.\/browser.js&quot; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ modules\/list\/list.js  \/\/ \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 var _ = require('lodash'); var vow = require('vow'); var console = require('console');  \/\/ DAL-\u043c\u043e\u0434\u0443\u043b\u044c var dal = require('.\/dal');  \/\/ \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 var Point = require('..\/Point'); var user = require('..\/user');  var list = {}; var cache = {}; \/\/ \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u044d\u0448  \/**  * \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u043b  * @param {Point} newPoint  * @returns {vow.Promise} resolve with {Point}  *\/ list.addPoint = function (newPoint) { \/* ... *\/ }  \/**  * \u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u0443\u043d\u043a\u0442 \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439  * @param {String} pointId  * @returns {vow.Promise}  *\/ list.checkPoint = function (pointId) { \/* ... *\/ }  \/**  * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u043f\u0443\u043d\u043a\u0442\u044b \u0432 \u0441\u043f\u0438\u0441\u043a\u0435  * @returns {vow.Promise} resolve with {Point[]}  *\/ list.getPoints = function () {     console.log('list \/ getPoints');      return new vow.Promise(function (resolve, reject) {         var userId = user.getId();          if (_.isArray(cache[userId])) {             resolve(cache[userId]);             return;         }          dal.getPoints(user)             .then(function (points) {                 cache[userId] = points;                  console.log('list \/ getPoints: resolve', cache[userId]);                 resolve(points);             }, reject);     }); }  module.exports = list; <\/code><\/pre>\n<p>  \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u043e \u043c\u043e\u0434\u0443\u043b\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u043b\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:  <\/p>\n<pre><code>modules   \u251c\u2500\u2500 dal   \u2502\u00a0\u00a0 \u251c\u2500\u2500 browser   \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 rest.js   \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 sessionStorage.js   \u2502\u00a0\u00a0 \u2514\u2500\u2500 node   \u2502\u00a0\u00a0     \u2514\u2500\u2500 memcache.js   \u251c\u2500\u2500 list   \u2502\u00a0\u00a0 \u251c\u2500\u2500 dal   \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 browser.js  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 dal\/browser\/rest.js   \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 node.js  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 dal\/node\/memcache.js   \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 package.json   \u2502\u00a0\u00a0 \u251c\u2500\u2500 list.js   \u2502\u00a0\u00a0 \u2514\u2500\u2500 package.json   \u251c\u2500\u2500 Point   \u2502\u00a0\u00a0 \u251c\u2500\u2500 package.json   \u2502\u00a0\u00a0 \u2514\u2500\u2500 Point.js   \u2514\u2500\u2500 user       \u251c\u2500\u2500 dal       \u2502\u00a0\u00a0 \u251c\u2500\u2500 browser.js \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 dal\/browser\/sessionStorage.js       \u2502\u00a0\u00a0 \u251c\u2500\u2500 node.js       \u2502\u00a0\u00a0 \u2514\u2500\u2500 package.json       \u251c\u2500\u2500 package.json       \u2514\u2500\u2500 user.js  <\/code><\/pre>\n<h4>\u0412\u0441\u0451 \u0432\u043c\u0435\u0441\u0442\u0435<\/h4>\n<p>  \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430 \u0432 ToDo-\u043b\u0438\u0441\u0442:  <\/p>\n<pre><code class=\"javascript\">\/\/ client\/todo.js \/\/ ...     \/\/ \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043c\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438     var console = require('console');     var _ = require('lodash');      var list = require('..\/modules\/list');     var Point = require('..\/modules\/Point');      var todo = {         addPoint: function (description) {             var point = new Point({                 description: description             });              list.addPoint(point);         }     }; \/\/ ... <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 todo.addPoint(&#8216;Test&#8217;)? \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u044e \u0438\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430\u0445. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430<\/b><\/p>\n<div class=\"spoiler_text\"><img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/64c\/019\/0fe\/64c0190fe78d7a708f2105c88baf3e18.png\"\/>  <\/div>\n<\/div>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043c\u043e\u0434\u0443\u043b\u044c list 2 \u0440\u0430\u0437\u0430 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0432\u043e\u0435\u043c\u0443 DAL-\u043c\u043e\u0434\u0443\u043b\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 http-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043d\u0430\u0448\u0435\u043c\u0443 API.<br \/>  \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0442\u0435\u0445 \u0436\u0435 (\u043f\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0447\u0430\u0441\u0442\u0438) \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435<\/b><\/p>\n<div class=\"spoiler_text\"><img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/f3b\/69c\/0c1\/f3b69c0c1b1e36727b8df2465c7e993a.png\"\/>   <\/div>\n<\/div>\n<p>  \u0412\u043e\u0442 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f: \u0441\u0445\u0435\u043c\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438 DAL-\u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u0430. \u041e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f, \u043a\u0430\u043a \u043c\u044b \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u0438, \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 DAL-\u0443\u0440\u043e\u0432\u043d\u0435.<\/p>\n<p>  \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0435\u0439\u0441 \u0441 \u00ab\u0437\u0430\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435\u043c\u00bb \u043f\u0443\u043d\u043a\u0442\u0430:  <\/p>\n<pre><code class=\"javascript\">list.checkPoint(pointId); <\/code><\/pre>\n<p>  \u0415\u0449\u0451 \u043f\u0430\u0440\u0430 \u043c\u0438\u043d\u0443\u0442 \u2014 \u0438 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0433\u043e\u0442\u043e\u0432\u043e.  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434.\u0427\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e?<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/\/ client\/todo.js  (function () {     var console = require('console');     var _ = require('lodash');      var list = require('..\/modules\/list');     var Point = require('..\/modules\/Point');      var listContainer = document.getElementById('todo_list');     var newPointContainer = document.getElementById('todo_new_point_description');      var tmpl = '&lt;ul&gt;'         + '&lt;% _.forEach(points, function(point) { %&gt;'         + '&lt;li data-id=&quot;&lt;%- point.getId() %&gt;&quot; data-checked=&quot;&lt;%- point.getIsChecked() ? 1 : \\'\\' %&gt;&quot; class=&quot;&lt;% if (point.getIsChecked()) { %&gt;todo_point_checked &lt;% }; %&gt;&quot;&gt;'         + '&lt;%- point.getDescription() %&gt;'         + '&lt;\/li&gt;&lt;% }); %&gt;'         + '&lt;\/ul&gt;';      var todo = {         addPoint: function (description) {             var point = new Point({                 description: description             });              list.addPoint(point)                 .then(todo.render, todo.error);         },         checkPoint: function (pointId) {             list.checkPoint(pointId)                 .then(todo.render, todo.error);         },         render: function () {             list.getPoints()                 .then(function (points) {                     listContainer.innerHTML = _.template(tmpl, { points: points });                 });         },         error: function (err) {             alert(err);         }     };      newPointContainer.addEventListener('keyup', function (ev) {         if (ev.keyCode == 13 && ev.ctrlKey && newPointContainer.value) {             todo.addPoint(newPointContainer.value);             newPointContainer.value = '';         }     });      listContainer.addEventListener('click', function (ev) {         var targetData = ev.target.dataset;          if (!targetData.checked) {             console.debug(targetData.checked);             todo.checkPoint(targetData.id);         }     });      todo.render();  })(); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <b>\u041a\u043e\u0434 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/b>: <a href=\"https:\/\/github.com\/psyduckinattack\/todo-commonjs\">github<\/a>.<\/p>\n<h4>\u041e\u0441\u043c\u044b\u0441\u043b\u0438\u043c<\/h4>\n<p>  \u041a \u0447\u0435\u043c\u0443, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432\u0435\u0441\u044c \u044d\u0442\u043e\u0442 \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440? \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0440\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0435 \u043e\u0442 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u0440\u044f\u0434 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e \u0435\u0451 \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e\u0441\u0442\u0438. \u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u0430 \u0434\u0430\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u0433\u0434\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0435\u0451 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f? \u0413\u043e\u0442\u043e\u0432 \u043b\u0438 \u044f \u043c\u0438\u0440\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0435\u0438\u0437\u0431\u0435\u0436\u043d\u044b\u043c\u0438 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u043c\u0438 \u0440\u0430\u0441\u0445\u043e\u0434\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439? <\/p>\n<p>  \u0414\u043e \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u0434\u0430\u043b\u0435\u043a\u043e. \u0412 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0445\u043e\u0440\u043e\u0448\u043e \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435 \u0438 \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438. \u041a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438 \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u0438 \u043d\u0435\u0442?      \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/222261\/\"> http:\/\/habrahabr.ru\/post\/222261\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/383\/9b2\/f05\/3839b2f05fce04cfa7602d5375950e82.png\" align=\"right\"\/>  <\/p>\n<h4>\u041e \u0447\u0451\u043c \u0440\u0435\u0447\u044c?<\/h4>\n<p>  \u041e JS \u043c\u043e\u0434\u0443\u043b\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u041e\u0431 \u0438\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445. \u041c\u0435\u043d\u044c\u0448\u0435 \u0442\u0435\u043e\u0440\u0438\u0438, \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u0443\u0440\u0441\u0430 \u043c\u043e\u043b\u043e\u0434\u043e\u0433\u043e \u0431\u043e\u0439\u0446\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0438 \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0431\u0430\u0437\u0435 Node.JS: ToDo-\u043b\u0438\u0441\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442:  <\/p>\n<ol>\n<li>\u00ab\u0417\u0430\u0432\u0435\u0441\u0442\u0438\u00bb \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 Express;<\/li>\n<li>\u041d\u0430\u0443\u0447\u0438\u0442\u044c \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438;<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c;<\/li>\n<li>\u0422\u0430\u043a\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c ToDo-\u043b\u0438\u0441\u0442;<\/li>\n<li>\u041e\u0441\u043c\u044b\u0441\u043b\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/li>\n<\/ol>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-222261","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/222261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=222261"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/222261\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=222261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=222261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=222261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}