Комментарии 46
В нормально спроектированном node.js приложении require вызывается в момент инициализации (который происходит 1 раз) либо, когда очень нужно, вне критических к производительности кусках кода (которые повторяются много раз). Если require тормозит работу Вашего приложения — проблема не в require.
Единственная проблема — его ещё нет
IE6 вышел в 2001 и только что ушёл со сцены до такого состояния что можно его не учитывать.
С такой скоростью, на IE 10 можно будет положиться в 2020 году
AJAX это еще ладно, тут более-менее логично и асинхронные вызовы рулят. А вот когда кодируешь макароны для html5 sql, который работает через асинхронные функции — вот где ненавидишь JS… И думаешь какой мудак такое придумал и ждешь релиза или хотя бы бета версии Dart.
Вообще, задача какая-то надуманная. В реальном проекте за такое руки можно оторвать программисту. С AJAX проблем обычно нет, обычно получаешь нужные данные за один-два запроса.
Задача не надуманная, в реальном проекте (что-то вроде соцсети) был только список пользователей и детали каждого пользователя. Rest API фиксированный и менять под свои потребности (чтобы вместо списка возвращал сразу детали пользователя) нельзя.
В таких ситуациях согласен, приходиться городить костыли. Хотя, думаю, такой API лучше вызывать на сервер-сайде, чтобы закешировать результаты и предоставить более лаконичный API для локального JS кода.
«API лучше вызывать на сервер-сайде» — это то же самое что сделать вызовы синхронными, не так ли? Сервер-сайд же всегда синхронен. Т.е. сервер синхронно обойдёт весь список и сформирует новый список.

И кэш совершенно не поможет, если нужны актуальные данные. Вот, к примеру, добавится четвертый элемент в список, как сервер узнает что список изменён и текущий кэш больше невалидный? Либо сервер должен опрашивать каждую секунду оригинальный API из-за чего просядет перформанс, либо сервер оригинальный API будет опрашивать при каждом запросе. Но зачем тогда вообще нужен кэш?
>Сервер-сайд же всегда синхронен
нет, не всегда, даже ваш php кажется умеет потоки, правда через одно место, но умеет

>Но зачем тогда вообще нужен кэш?
Кеш нужен, чтобы ваши клиенты не матюгались, что их страничка грузится over 9000 секунд. Кеш бывает разный, можно настроить сброс через пару минут, а можно и через час. Важно то, что клиент будет делать один запрос, а не over 9000 пусть и не на ваш, а на сервер API, но это для клиента все равно накладно.
Есть сильное подозрение, что и Dart будет испольовать асинхронное API для работы с внешними ресурсами или WebWorkers. Причина банальна: асинхронные интерфейсы лучше приспособлены к условиям параллельного выполнения. Так что приучайтесь работать с колбэками и promises.

Есть ряд идей относительно поддержки асинхронных вызовов на уровне языка: async-await в C# или await-defer в IcedCoffeeScript
Не нужно пихать асинхронные вызовы везде, где можно. В dart надеюсь такого не будет или будет выбор.

Зачем мне асинхронный вызов для SQL запроса — городить из-за этого кучу лишнего кода. Когда, по сути, без получения этих данных нужно их всё равно ждать.

В java, например, есть выбор. Хочешь асинхронно создавай Future и работай дальше. Не хочешь, просто делай вызов. А в javascript — всё у нас будет асинхронно, ну и получается в итоге полный пздец в коде.
>> Зачем мне асинхронный вызов для SQL запроса

Например, запись статистики
Но в большинстве задач это лишнее и достаточно синхронного вызова функции. Но выбора нет и приходиться писать кучу кода ради одного sql запроса.
Я хорошо понимаю, о чем вы. Но JS тут не при чем — это все проблемы асинхронного API. Никакими дартами асинхронное не сделать синхронным.

А макароны эти вполне решабельны (за подробностями в личку, т.к. пока не production).
Понятно, что это API и понятно для какого языка проектировалось это API. Просто, надеюсь, что в dart'е это сделают удобнее.
Я лучше макароны буду распутывать, чем писать для веба на не прототипном языке.
*facepalm*
вот вам немножко знаний.

>Асинхронный вызов всегда лучше синхронного с точки зрения производительности. Посмотрите, например, на nginx — он стал суперпопулярным именно из-за высокой производительности, которая достигается, в основном, асинхронной работе.
Ну не надо путать то когда ты работаешь с системными вызовами и уже более высокоуровневые надстройки. Нет никакого оверхеда на синхронные вызовы. Посмотрите на C#, Haskell, Erlang, Python и то как решаются эти проблемы там.
Большое спасибо за книгу
На синхронный вызов, разумеется, нет оверхеда, но на отдельный поток (неважно, ядерный или виртуальный) оверхед есть и по памяти и по cpu. В апаче, например, каждый коннект жрёт 10 мб минимум.
Надеюсь понимаете что те 10мб — это виртуальная память под стэк, в котором хранится текущее состояние. Так вот, давайте теперь пойдём по пути, который вам так нравится и возьмём nginx. В nginx'е в heap'е выделяется кусок памяти под текущее состояние и реализуется fsm'ка, но даже тут мы можем применить магию вроде protothreads и получить безстэковые треды и при этом программист будет работать с синхронным API. Компилятор будет генерировать точно такой же код, который мы бы получили используя кучу switch/case'ов без protothread'ов.
Когда говорят про асинхронные вызовы и производительность, подразумевают системные вызовы, а не то что мы можем вокруг них накрутить и сделать всё так что программист будет работать с синхронным API.
С этим можно поспорить.
Под promise понимается несколько понятий.
Вот, например есть концепция CommonJS/Promises A jQuery.Deferred основан на ней.«jQuery.Deferred is based on the CommonJS Promises/A design». С этой точки зрения jQuery Deferred===CommonJS Promise

Ну и есть понятие конкретного promise как откушенный кусок от Deferred без функций reject и resolve, здесь — да, Promise !== Deferred
Так как в статье речь идет об использовании именно jQuery.Deferred, то высказывание «promise, также известен как Deferred» как минимум не совсем корректно.

Про CommonJS Promises/A я знаю, но, прошу заметить, там описана концепция именно «promise», то есть «отложенного» значения, а не структуры непосредственно реализовывающей возврат значения, как это делает jQuery Deferred. Так что, я продолжаю настаивать, что Deferred !== Promise.
Корутины обречены в JavaScript, у них нет будущего, т.к. программист не может быть уверен в собственном коде.
Например
var a = my.b;
my.b = my.c
my.c = get(a);

Что произойдёт если get сделает yield и возовновит работу после каких-то там событий? Эти события могут работать с my и они его увидят в промежуточном состоянии когда my.b = my.c потому что my.c ещё не обновлён.

В топку! Без изменения синтаксиса языка ничего уже не улучшить.
Coroutines no!, generators yes!
Проблемы с выдачей отсортированного списка несколько надуманны — можно делать запрос не для каждой айдишки, а для массива, возвращая с сервера массив объектов.
Понятия синхронности и ассинхронности связаны с порядком вычислений. В первом случае он важен, во втором не имеет значения. блокировки это самый простой способ обеспечить последовательное вычисление. Вообще говоря, в классическом джаваскрипте нет примитивов для рассинхронизации порядка вычислений. в популярных реализациях это делается исключительно на уровне рантайма. Поэтому говорить об ассинхронности js как языка в данном случае безосновательно.
К моему большому сожалению, node.js всё-таки не удержался и ввёл ещё одну синхронную комманду — require. Пока эта комманда есть в node.js, я, лично никогда не буду использовать его, ибо убеждён что производительность будет всегда хромать.

Все require вызываются при инициализации приложения, какое влияние на производительность?
http.createServer(function(request, response) {
	var mymod = require("./mymod.js");
}).listen(8888);
— не при инициализации приложения.
Никто не спорит что она закешированная и всё такое, но она синхронная
Жесть. Кто вам такое показал?

Вот как оно делается:

var mymod = require("./mymod.js");
http.createServer(function(request, response) {

}).listen(8888);

Библиотеки подключаются до инициализации сервера, как и все остальное, что можно сделать при запуске приложения.
А смысл это делать каждый запрос?
var mymod = require("./mymod.js");
http.createServer(function(request, response) {
    // use mymod here
}).listen(8888);
Вот еще очень удобный вариант.
http.createServer(function(request, response) {
var counter = 0;
for(var i1 = 0; i1 < 1000000000; i1++)
for(var i2 = 0; i2 < 1000000000; i2++)
for(var i3 = 0; i3 < 1000000000; i3++)
counter++;
var mymod = require("./mymod.js");
}).listen(8888);
Интересная статья, как раз с похожей задачей сейчас имею дело, но, на другом языке. По-моему вариант с $.when можно немного упростить, но, в целом, суть и так ясна. Спасибо!
Почему «Вариант 2» Нужно избегать? На twisted'е я так и пишу, тут разницы особой нет JS это или Python. Чем плох этот вариант? Сложностью? Это — проблемы того кто не понимает сам что пишет.
Сложность — раз
резолв ждёт выполнения самого медленного запроса из списка — два
неопределённость — если хотя бы один из элементов вернул reject, весь массив реджектится или всё-таки резолвятся валидные значения? — три
ну вот опять этот некрасивый каскадный код. что мешает вам писать иначе? это же Javascript!

(function() {
someAction1(data, callback1);

function callback1(error, data) {
someAction2(data, callback2);
}

function callback2(error, data) {
someAction3(data, callback3);
}

/* и т.д. */
})();


конечно немного длиннее, зато прозрачно и последовательно.

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

А вот предложение про node.js и require как уже заметили вообще не имеет смысла.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Меня удивил вывод про IE must die. Я так понимаю что его как минимум надо заменить на «Старые браузеры не поддерживающие webworker — must die».

А если вспомнить что на 1 февраля 2012 WebWorker это все еще draft (как собственно и весь html5) то фразу следует переделать в «Старые браузеры не поддерживающие неокончательно принятую фичю в которой еще может все измениться — must die».

Как-то неправильно это звучит в итоге…
JavaScript 1.7, где есть генераторы, которые могут решать эту же проблему, не драфт с октября 2006, а в IE не поддерживаются тоже
интересный ответ, но:

в последней версии ecmascript 5.1 (июнь 2011) генераторов нет, yield только как future reserved word. А современные браузеры ориентируются именно на ecmascript.

генераторы уже давно есть в javaScript 1.7 который курируется Mozilla Foundation, и собственно только используется в js движке от Mozilla (причем не как дефолт, а как расширение которое можно включить типом скрипта).

Делает ли это отстоем все остальные (не Mozilla based) браузеры? Я думаю нет.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.