Архив метки: Javascript

Кратко про GraphQL

В отпуске появилось по-больше свободного времени, чтобы «оглянуться по сторонам» и заняться давно интересовавшими меня технологиями. В этой записи будет краткое резюме по GraphQL.

GraphQL — это стандарт декларирования структуры данных и способов получения данных, предложенный и реализованный Facebook.

Существует несколько реализаций GraphQL:

  1. От Facebook — http://graphql.org/code/ Тут, правда, странность в том, что базовую технологию https://github.com/graphql/graphql-js не рекомендуют к production. Там же в наборе есть Relay — в чём-то аналог Redux, заточенный на выемку данных с помощью GraphQL-запросов.
  2. От Apollo — http://www.apollostack.com/ Тут ребята постарались сделать full-stack, причем клиентская часть основана на Redux. Минус их в том, что есть задержка в реализации последних версий стандарта GraphQL: сейчас, например, нет stream, defer и пр., технологий ускоряющих работу с многостраничными данными и часто-обновлямыми элементами. Не думаю, что это прям критичный минус, но это стоит учитывать.
  3. И еще 3-4 штуки можно найти тут — https://github.com/chentsulin/awesome-graphql.

Там же можно найти библиотеки, реализующие GraphQL, на практически всех современных языках программирования, кучу различных примеров реализаций, способов визуализации запросов и пр. и пр.

Что мне понравилось в этой технологии:

1. Декларативное описание структур данных, которые можно запросить с сервера. Только посмотрите на эту красоту:

type Entity {
  _id: String
  title: String
  category: EntityCategory
}

type EntityCategory {
  _id: String
  title: String
}

type RootQuery {
  entity(_id: String): Entity
  entities(limit: Int): [Entity]
}

schema {
  query: RootQuery
}

Так мы описали, например, что с сервера можно запросить Entity с полями _id, title, category типа EntityCategory. В apollo-stack эта строка будет автоматически преобразована в стандартный объект GraphQLSchema.

2. Удобное написание функций, получающих данные (resolvers):

module.exports = {
    RootQuery: {
        entity(_, { _id }) {
            // Тут ожидается либо Promise, либо просто значение
            return vEntities.vertex(_id).then(v => v.vertex);
        },
        entities() {
            return vEntities.all().then(cursor => cursor.all());
        }
    },

    Entity: {
        // Эта функция будет вызвана, только если у Entity также запросили category. Также можно вернуть Promise, который зарезолвится с нужными данными.
        category(entity) {
            return { _id: 1, title: 'Category A' };
        }
    }
};

3. Язык запроса данных и Web UI GraphiQL (супер легко подключается к express) с очень крутой валидацией запросов и auto-complete, который учитывает текущую схему. Например, запросим только поле title у Entity по id:

{
  entity(id: "1") {
    title
  }
}

Из минусов можно отметить не очень понятную документацию на graphql.org (а вот у Apollo по тем же вопросам документация отличная) и официальная клиентская библиотека Relay, использование которой означает отказ от Redux.

Итого

Я вижу GraphQL как весьма удобную альтернативу классическому REST API: гораздо удобнее иметь одну «ручку», в которую можно слать разнообразные запросы на получение или изменение данных (тут они называются мутациями (mutation) и декларативное описание структуры данных, чем портянку из обработчиков путей типа req.get(‘/entities’), req.post(‘/entitites’), req.put(‘/entities/:entityId’) и т.д.

Также такой подход облегчает формирование единого state для react-приложений.

ENB плагин для конвертации javascript из стандарта ES2015 в ES5

Оформил наконец в виде npm-пакета ENB технологию конвертации javascript кода из нового стандарта (es2015) в старый (es5), чтобы все браузеры могли работать c таким кодом.

Из интересного:

  • Преобразованный код не содержит лишнего, т.к. выбраны babel плагины, которые не добавляют дополнительный runtime;
  • Преобразуется довольно быстро по след. причинам:
    • Полностью заменяет стандартную технологию компиляции js — enb-js;
    • Код библиотек не преобразуется;
    • Нет sourcemaps (это, впрочем, и минус тоже).

Пакет с технологией тут — https://www.npmjs.com/package/enb-es2015

Спасибо @tenorok за изначальный код технологии.

HTML5 & Math: Треугольник Серпинского на canvas

Проходя (даже можно сказать, пробиваясь с потерями через) книгу Д. Кнута «Искусство программирования» встретил треугольник Паскаля, а тут еще давно надо было разобраться с html5 canvas, поэтому возникло непреодолимое желание проиллюстрировать треугольник Паскаля на canvas.

Есть довольно интересный способ иллюстрации числовых последовательностей в этом треугольнике – треугольник Серпинского, его я и изобразил. Вкратце, цветом отмечаются четные числа в этом треугольника.

Код реализации ниже.

	<canvas id="pascalCanvas" width="1500" height="1500"></canvas>

	<script>

		function drawPixel(x, y, context) {
			context.fillRect(x, y, 1, 1);
		}

		canvas = document.getElementById("pascalCanvas");
		c = canvas.getContext("2d");

		//some gradient style
		var gradient = c.createLinearGradient(0, 0, 0, canvas.height);
		gradient.addColorStop(0, "#abc");
		gradient.addColorStop(1, "#000");
		c.fillStyle = gradient;
		//c.fillStyle = "#000";

		//Pascal's triangle
		var tr = new Array(canvas.height);
		for (i = 0; i < canvas.height; i++) {
			tr[i] = new Array(canvas.width);
			for (k = 0; k < canvas.width; k++) {
				if (k == 0)
					tr[i][k] = 1;
				else
					tr[i][k] = 0;
			}
		}

		for (i = 1; i < canvas.height; i++) {
			for (k = 1; k < canvas.width; k++) {
				tr[i][k] = (tr[i-1][k-1] + tr[i-1][k]) % 2;
			}
		}

		//draw
		for (i = 0; i < canvas.height; i++) {
			for (k = 0; k < canvas.width; k++) {
				if (tr[i][k] != 0)
				drawPixel(k, i , c);
			}
		}
	</script>

Получается такое:

треугольник Серпинского на html canvas

Треугольник Серпинского на html canvas

Посмотреть «в живую»

PS: Ну и раз недавно был день св. Валентина =):

Валентинка Серпинского с http://xkcd.ru/543/


Дизайн: jQuery плагин "Удобная кнопка удаления"

Собрался с силами и таки написал реализацию концепта более юзабельной кнопки удаления.)

Как это выглядит

Как это работает можно посмотреть на отдельной странице плагина. Там же можно скачать исходные коды и минифицированную версию плагина.

Как это устроено

Для начала примем, что кнопка удаления — это ссылка-кнопка с GET-параметрами для удаления какого-либо объекта из базы данных. Ссылка будет что-то типа такой: «http://example.ru/?action=delete&item_id=9000«.

При инициализации старая кнопка удаляется и на её месте с помощью абсолютного позиционирования размещается новая кнопка-ссылка со ссылкой для удаления, указанной в параметрах. Также добавляется скрытый элемент — панель с диалогом подтверждения удаления.

При нажатии на кнопку удаления из-под неё выдвигается панель с диалогом подтверждения удаления. Размещение элементов друг над другом возможно благодаря использованию связки CSS-аттрибутов: у кнопки удаления

position: absolute; z-index: 10

и у панели

position: absolute; z-index: 1