Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Monday, 5 October 2015

ES6: методы против коллбэков

Существует тонкое различие между объектом и методами объекта с обратных вызовов.

Объект, свойства которого являются методами

Параметр this метода является получателем вызова метода (например, obj если вызов метода obj.m (···)).

Например, вы можете использовать WHATWG потоков API следующим образом:


let surroundingObject = {
surroundingMethod() {
let obj = {
data: 'abc',
start(controller) {
···
console.log(this.data); // abc (*)
this.pull(); // (**)
···
},
pull() {
···
},
cancel() {
···
},
};
let stream = new ReadableStream(obj);
},
};


То есть, `obj` является объектом, свойства которого` start`, `и` pull` cancel` методы. Соответственно, эти методы можно использовать `this` для доступа к объектно-локального состояния (линия *) и называть друг друга (линии **).


Объект, свойства которого callbacks

Параметр `this` из функции стрелки является` this` окружающей рамки (лексический это). Arrow функции делать отличные Обратные вызовы, потому что это поведение обычно хотят для обратного вызова (реальной, не-метод функций). Обратный вызов не должен иметь свой собственный это, что тенями `this` окружающей области.

Если свойства `start`,` и `pull` cancel` являются стрелками функций, то они подобрать` `this` из surroundingMethod ()` (окружающей их охват):


let surroundingObject = {
surroundingData: 'xyz',
surroundingMethod() {
let obj = {
start: controller => {
···
console.log(this.surroundingData); // xyz (*)
···
},

pull: () => {
···
},

cancel: () => {
···
},
};
let stream = new ReadableStream(obj);
},
};
let stream = new ReadableStream();

Если выход в линии * удивляет вас, то рассмотрим следующий код:


let obj = {
foo: 123,
bar() {
let f = () => console.log(this.foo); // 123
let o = {
p: () => console.log(this.foo), // 123
};
},
}

Внутри метода bar(), f и o.p работать так же, потому что обе функции со стрелками имеют те же окружающий лексическую область bar(). Последняя функция стрелка в окружении объекта буквальном не изменить.

Friday, 2 October 2015

NodeJS 4.0.0 8% быстрее - мы проверили его!

NodeJS и iojs встретились в середине и сталь одним проектом снова! Нет больше пытаются решить, какой из них использовать. Они также объявили о своих планах выпуска, которые интересно. Две большие релизы в год и в довершение, там будет версия LTS узла, который, мы надеемся, сделать прецедент легче в условиях, когда жизненные циклы больше.


Как вы знаете, мы большие поклонники Node здесь Raygun, поэтому подумал сделаю benchmark  Node 4.0.0 и определим насколка он быстрее!


Как тестировал


  • NodeJS и io.js работает на Mac OS X Yosemite, полностью в актуальном состоянии на частоте 2,5 ГГц i7 Macbook Pro с 16G оперативной памяти
  • Ubuntu VM, используя WRK, 12 потоки, 400 одновременных соединений более 30 секунд отправляя небольшой Raygun стиле полезную нагрузку в маленькую ExpressJS сайте, который возвращает то, что отправил на него

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


Если вы следили за Node / io.js на некоторое время теперь, вы будете знать, что последняя версия использует последнюю версию V8, который включает в себя кучу новых ECMA 6 функций. Он также должен быть быстрее, будучи новым.



С самого быстрого теста здесь, Node 4.0.0 около 8% быстрее, чем Node 0.12.7 При работе с той же нагрузке. Это не плохо для простого обновления, особенно если умножить его на нескольких серверах!

Dependency Injection в Node.js

Dependency injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object.

Причины для использования Dependency Injection


Развязка


Внедрение зависимостей делает ваши модули менее связаны приводит к более обслуживаемой кода.


Легче модульного тестирования


Вместо того чтобы использовать жестко закодированные зависимостей вы можете передать их в модуль вы хотели бы использовать. С этой картины в большинстве случаев, вы не должны использовать модули, как proxyquire.


Ускорение разработки


С инъекции зависимостей, после интерфейсы определены легко работать без каких-либо конфликтов слияния.


Как использовать Dependency Injection используя Node.js


Во-первых, давайте взглянем на то, как вы могли бы написать свои приложения без использования инъекции зависимостей, и как бы вы преобразовать его.


Образец модуля без dependency injection


// team.js
var User = require('./user');

function getTeam(teamId) {  
  return User.find({teamId: teamId});
}

module.exports.getTeam = getTeam;  

Простой тест будет выглядеть так:


// team.spec.js
var Team = require('./team');  
var User = require('./user');

describe('Team', function() {  
  it('#getTeam', function* () {
    var users = [{id: 1, id: 2}];

    this.sandbox.stub(User, 'find', function() {
      return Promise.resolve(users);
    });

    var team = yield team.getTeam();

    expect(team).to.eql(users);
  });
});

То, что мы сделали здесь является то, что мы создали файл с именем team.js, которые могут возвращать список пользователей, которые принадлежат к одной команде. Для этого нам потребуется модель User, так что мы можем вызвать его метод, который возвращает find список пользователей.


Выглядит хорошо, не так ли? Но когда дело доходит до тестирования, мы должны использовать тестовые заглушки с sinon.


В тестовом файле, мы должны потребовать модель User, так что мы можем заглушки свой метод find. Заметьте, что мы используем функцию песочницы здесь, так что мы не придется вручную восстановить исходную функцию после выполнения теста.


Sample module with dependency injection


/ team.js
function Team(options) {  
  this.options = options;
}

Team.prototype.getTeam = function(teamId) {  
  return this.options.User.find({teamId: teamId})
}

function create(options) {  
  return new Team(options);
}

Вы можете проверить это файл со следующим теста:


// team.spec.js
var Team = require('./team');

describe('Team', function() {  
  it('#getTeam', function* () {
    var users = [{id: 1, id: 2}];

    var fakeUser = {
      find: function() {
        return Promise.resolve(users);
      }
    };

    var team = Team.create({
      User: fakeUser
    });

    var team = yield team.getTeam();

    expect(team).to.eql(users);
  });
});

Хорошо, так как версия с инъекции зависимостей отличается от предыдущей? Первое, что можно заметить, является использование factory pattern: мы используем это, чтобы придать вариантов / зависимостей для вновь созданного объекта - это когда мы можем придать модели User.


В тестового файла мы должны создать поддельный модель, которая будет представлять модель User, то мы просто ввести это путем передачи его в create функции Team модели. Легко, не так ли?


Dependency Injection в реальных проектах


Вы можете найти примеры внедрения зависимостей в много проектов с открытым кодом. Например, большинство Express/Koa middlewares, которые вы используете в вашей повседневной работе использует ту же самую подход.


Express middlewares


var express = require('express');  
var app = express();  
var session = require('express-session');

app.use(session({  
  store: require('connect-session-knex')()
}));

Фрагмент кода выше, используя зависимость инъекций с заводской схеме: на сессии промежуточного мы передаем модуль connect-session-knex - он должен реализовать интерфейс, что модуль session будет звонить.


В этом случае модуль connect-session-knex должен реализовать следующие методы:


  • store.destroy(sid, callback)
  • store.get(sid, callback)
  • store.set(sid, session, callback)

 

Monday, 7 September 2015

Простое ленивый загрузка изображение с Эффектом

Один из самых быстрых и простых оптимизации производительности веб-сайт снижается загрузку изображений. Это означает, что множество вещей, в том числе minifying изображения с инструментами, как ImageOptim и TinyPNG, используя URI, данных и спрайты, и ленивые изображения загрузки. Это немного резкий, когда вы ленивые изображения загрузки, и они просто не появляются из ниоткуда, который является, почему я люблю замирание в маршруте. Страница все еще тасует если вы явно не установив размеры изображения, но исчезают в действительно обеспечивает крошечную класса. Я видел много решений, которые выполнения этого (некоторые не очень хорошо, как мой старый метод), поэтому я думал, что я хотел бы поделиться моей текущей реализации.

HTML

<img alt="" data-src="/path/to/image.jpg" />

Использование data-src представлять возможную URL.

CSS

Любое изображение с атрибутом данных SRC должна начинаться как невидимые и в конечном итоге переход на непрозрачность:

img {
opacity: 1;
transition: opacity 0.3s;
}

img[data-src] {
opacity: 0;
}


Вы, наверное, можете догадаться, в данный момент, что мы будем делать с этим атрибутом, когда изображение загружается ...

JavaScript

Удалением атрибута data-src, когда изображение загружен:

[].forEach.call(document.querySelectorAll('img[data-src]'), function(img) {
img.setAttribute('src', img.getAttribute('data-src'));
img.onload = function() {
img.removeAttribute('data-src');
};
});


Это решение требует JavaScript. Для решения запасного варианта вы можете сделать это:

[].forEach.call(document.querySelectorAll('noscript'), function(noscript) {
var img = new Image();
img.setAttribute('data-src', '');
img.parentNode.insertBefore(img, noscript);
img.onload = function() {
img.removeAttribute('data-src');
};
img.src = noscript.getAttribute('data-src');
});


Это супер основной руководство, но учитывая, что я видел так много других решений, он работает под каждого сценария, я проверил, в том числе истории изменений через AJAX.

Конечно, это не принимать во внимание прокрутки на основе ленивой нагрузки но это обычно делается плагином в Вашем любимом рамках JavaScript или самостоятельный компонентом. Если вы ищете простое решение, то, это он!