My-library.info
Все категории

Марейн Хавербеке - Выразительный JavaScript

На электронном книжном портале my-library.info можно читать бесплатно книги онлайн без регистрации, в том числе Марейн Хавербеке - Выразительный JavaScript. Жанр: Программирование издательство неизвестно, год 2004. В онлайн доступе вы получите полную версию книги с кратким содержанием для ознакомления, сможете читать аннотацию к книге (предисловие), увидеть рецензии тех, кто произведение уже прочитал и их экспертное мнение о прочитанном.
Кроме того, в библиотеке онлайн my-library.info вы найдете много новинок, которые заслуживают вашего внимания.

Название:
Выразительный JavaScript
Издательство:
неизвестно
ISBN:
-
Год:
неизвестен
Дата добавления:
17 сентябрь 2019
Количество просмотров:
276
Читать онлайн
Марейн Хавербеке - Выразительный JavaScript

Марейн Хавербеке - Выразительный JavaScript краткое содержание

Марейн Хавербеке - Выразительный JavaScript - описание и краткое содержание, автор Марейн Хавербеке, читайте бесплатно онлайн на сайте электронной библиотеки My-Library.Info
В процессе чтения вы познакомитесь с основами программирования и, в частности, языка JavaScript, а также выполните несколько небольших проектов. Один из самых интересных проектов — создание своего языка программирования.

Выразительный JavaScript читать онлайн бесплатно

Выразительный JavaScript - читать книгу онлайн бесплатно, автор Марейн Хавербеке

var http = require("http");

var Router = require("./router");

var ecstatic = require("ecstatic");


var fileServer = ecstatic({root: "./public"});

var router = new Router();


http.createServer(function(request, response) {

  if (!router.resolve(request, response))

    fileServer(request, response);

}).listen(8000);


Функции respond и respondJSON используются в коде сервера, чтобы можно было отправлять ответы одним вызовом функции.


function respond(response, status, data, type) {

  response.writeHead(status, {

    "Content-Type": type || "text/plain"

  });

  response.end(data);

}


function respondJSON(response, status, data) {

  respond(response, status, JSON.stringify(data),

          "application/json");

}

Темы как ресурсы

Сервер хранит предложенные темы в объекте talks, у которого именами свойств являются названия тем. Они будут выглядеть как ресурсы HTTP по адресу /talks/[title], поэтому нам нужно добавить в маршрутизатор обработчиков, реализующих различные методы, которые клиенты могут использовать для работы с ними.

Обработчик для запросов GET одной темы должен найти её и либо вернуть данные в JSON, либо выдать ошибку 404.

var talks = Object.create(null);


router.add("GET", /^/talks/([^/]+)$/,

           function(request, response, title) {

  if (title in talks)

    respondJSON(response, 200, talks[title]);

  else

    respond(response, 404, "No talk '" + title + "' found");

});


Удаление темы делается удалением из объекта talks.


router.add("DELETE", /^/talks/([^/]+)$/,

           function(request, response, title) {

  if (title in talks) {

    delete talks[title];

    registerChange(title);

  }

  respond(response, 204, null);

});

Функция registerChange, которую мы определим позже, уведомляет длинные запросы об изменениях.

Чтобы было просто получать контент тел запросов, закодированных при помощи JSON, мы определяем функцию readStreamAsJSON, которая читает всё содержимое потока, разбирает его по правилам JSON и затем делает обратный вызов.

function readStreamAsJSON(stream, callback) {

  var data = "";

  stream.on("data", function(chunk) {

    data += chunk;

  });

  stream.on("end", function() {

    var result, error;

    try { result = JSON.parse(data); }

    catch (e) { error = e; }

    callback(error, result);

  });

  stream.on("error", function(error) {

    callback(error);

  });

}

Один из обработчиков, которому нужно читать ответы в JSON – это обработчик PUT, который используется для создания новых тем. Он должен проверить, есть ли у данных свойства presenter и summary, которые должны быть строками. Данные, приходящие снаружи, всегда могут оказаться мусором, и мы не хотим, чтобы из-за плохого запроса была сломана наша система.

Если данные выглядят приемлемо, обработчик сохраняет объект, представляющий новую тему, в объекте talks, при этом, возможно, перезаписывая существующую тему с таким же заголовком, и опять вызывает registerChange.

router.add("PUT", /^/talks/([^/]+)$/,

           function(request, response, title) {

  readStreamAsJSON(request, function(error, talk) {

    if (error) {

      respond(response, 400, error.toString());

    } else if (!talk ||

               typeof talk.presenter != "string" ||

               typeof talk.summary != "string") {

      respond(response, 400, "Bad talk data");

    } else {

      talks[title] = {title: title,

                      presenter: talk.presenter,

                      summary: talk.summary,

                      comments: []};

      registerChange(title);

      respond(response, 204, null);

    }

  });

});

Добавление комментария к теме работает сходным образом. Мы используем readStreamAsJSON для получения содержимого сообщения, проверяем результирующие данные и сохраняем их как комментарий, если они приемлемы.

router.add("POST", /^/talks/([^/]+)/comments$/,

           function(request, response, title) {

  readStreamAsJSON(request, function(error, comment) {

    if (error) {

      respond(response, 400, error.toString());

    } else if (!comment ||

               typeof comment.author != "string" ||

               typeof comment.message != "string") {

      respond(response, 400, "Bad comment data");

    } else if (title in talks) {

      talks[title].comments.push(comment);

      registerChange(title);

      respond(response, 204, null);

    } else {

      respond(response, 404, "No talk '" + title + "' found");

    }

  });

});

Попытка добавить комментарий к несуществующей теме должна возвращать ошибку 404.

Поддержка длинных запросов

Самый интересный аспект сервера – часть, которая поддерживает длинные запросы. Когда на адрес /talks поступает запрос GET, это может быть простой запрос всех тем, или запрос на обновления с параметром changesSince.

Есть много различных ситуаций, в которых нам нужно отправить клиенту список тем, поэтому мы сначала определим вспомогательную функцию, присоединяющую поле serverTime к таким ответам.

function sendTalks(talks, response) {

  respondJSON(response, 200, {

    serverTime: Date.now(),

    talks: talks

  });

}

Обработчик должен посмотреть на все параметры запроса в его URL, чтобы проверить, не задан ли параметр changesSince. Если дать функции parse модуля “url” второй аргумент значения true, он также распарсит вторую часть URL – query, часть запроса. У возвращаемого объекта будет свойство query, в котором будет ещё один объект, с именами и значениями параметров.

router.add("GET", /^/talks$/, function(request, response) {

  var query = require("url").parse(request.url, true).query;

  if (query.changesSince == null) {

    var list = [];

    for (var title in talks)

      list.push(talks[title]);

    sendTalks(list, response);

  } else {

    var since = Number(query.changesSince);

    if (isNaN(since)) {

      respond(response, 400, "Invalid parameter");

    } else {

      var changed = getChangedTalks(since);

      if (changed.length > 0)

         sendTalks(changed, response);

      else

        waitForChanges(since, response);

    }

  }

});

При отсутствии параметра changesSince обработчик просто строит список всех тем и возвращает его.

Иначе, сперва надо проверить параметр changeSince на предмет того, что это число. Функция getChangedTalks, которую мы вскоре определим, возвращает массив изменённых тем с некоего заданного времени. Если она возвращает пустой массив, то серверу нечего возвращать клиенту, так что он сохраняет объект response (при помощи waitForChanges), чтобы ответить попозже.

var waiting = [];


function waitForChanges(since, response) {

  var waiter = {since: since, response: response};

  waiting.push(waiter);

  setTimeout(function() {

    var found = waiting.indexOf(waiter);

    if (found > -1) {

      waiting.splice(found, 1);

      sendTalks([], response);

    }

  }, 90 * 1000);

}

Метод splice используется для вырезания куска массива. Ему задаётся индекс и количество элементов, и он изменяет массив, удаляя это количество элементов после заданного индекса. В этом случае мы удаляем один элемент – объект, ждущий ответ, чей индекс мы узнали через indexOf. Если вы передадите дополнительные аргументы в splice, их значения будут вставлены в массив на заданной позиции, и заместят удалённые элементы.

Когда объект response сохранён в массиве waiting, задаётся таймаут. После 90 секунд он проверяет, ждёт ли ещё запрос, и если да – отправляет пустой ответ и удаляет его из массива waiting.

Чтобы найти именно те темы, которые сменились после заданного времени, нам надо отслеживать историю изменений. Регистрация изменения при помощи registerChange запомнит это изменение, вместе с текущим временем, в массиве changes. Когда случается изменение, это значит – есть новые данные, поэтому всем ждущим запросам можно немедленно ответить.

var changes = [];


function registerChange(title) {

  changes.push({title: title, time: Date.now()});

  waiting.forEach(function(waiter) {

    sendTalks(getChangedTalks(waiter.since), waiter.response);

  });

  waiting = [];

}

Наконец, getChangedTalks использует массив changes, чтобы построить массив изменившихся тем, включая объекты со свойством deleted для тем, которых уже не существует. При построении массива getChangedTalks должна убедиться, что одна и та же тема не включается дважды, так как тема могла измениться несколько раз с заданного момента времени.


Марейн Хавербеке читать все книги автора по порядку

Марейн Хавербеке - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки My-Library.Info.


Выразительный JavaScript отзывы

Отзывы читателей о книге Выразительный JavaScript, автор: Марейн Хавербеке. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.