Нет. В эрланге ты программируешь линейно. Сделал A, затем сделал B. В Node.JS ты программируешь через коллбеки: сделал A, которому скормил коллбек, который позовёт B. Это лапша.
1. Конечно, вопрос синтаксиса. И это важно чрезвычайно. Именно из-за синтаксиса мы не программируем на брейнфаке, а хотим более высокоуровневых и, одновременно, простых конструкций.
2. Кафеин не скрывает сложность модели выполнения Node.JS: всё равно нужно помнить, где восклицательные знаки расставлять. А если вдруг забыл - то всё заблокируется напрочь. Нельзя пропустить _ни одного_ восклицательного знака. Во всех тысячах строчек кода. Иначе именно этот пропущенный знак когда-нибудь выстрелит.
Не очень понял насчет заблокируется. Если пропустить восклицательный знак, то код после асинхронного вызова будет выполнен сразу же, а не "потом". А "потом" (после завершения асинхронной операции) не будет выполнено ничего. Например, если в первом примере по ссылке пропустить восклицательный знак, то append() будет вызван с неопределенным параметром.
Речь не только про append. Но и про остальные тыщи API-операций, часть которых лишь часть действительно асинхронна.
Я действительно допустил небрежность в объяснении. Не только восклицательные знаки нужно расставлять, но и избегать синхронных вызовов надо. То есть, ни одна функция, теоретически, не может быть безопасной для соседних потоков. Частью эта проблема решается соглашением о наименовании. Фольклором! А не особенностями VM, которые принципиально не допускают блокировки.
Кроме того, даже использование асинхронных функций сопряжено с граблями!
Например, потерянный коллбек блокировки даст неопределённый порядок применения операций:
node.fs.rename("/tmp/hello", "/tmp/world"); node.fs.stat("/tmp/world", function (status, stats) { ... });Вот здесь stat может выполниться раньше, чем завершится операция rename
( ... )
Насколько я знаю, синхронные в Node только штук 30 функций для файлового ввода-вывода. Это аналоги соответствующих асинхронных функций, добавленные "для удобства". Пользоваться ими категорически не рекомендуется по понятным причинам. Я считаю их вообще зря добавили и со временем уберут.
Кроме этих функций блокироваться практически больше нечему, если самому вечный цикл не написать. Никакого sleep(), например, нету. Поэтому, как правило, если процессор чем-нибудь занят то он занят полезной работой, а не читает тупо один и тот же адрес в памяти ради синхронизации потоков. Думаю, именно это имеется ввиду когда говорят "because nothing blocks".
я не специалист по node.js, но писал, маленько, на twisted. штука в том, что каждая пользовательская функция/метод синхронна по умолчанию. в смысле: файл-то он прочитает ассинхронно, но нужно, ведь, не только прочитать, но и распарсить, к примеру. а в такие штуки ассинхронность приходится руками засовывать. в какой-то момент говорить: "стоп - пускай теперь другие поработают". завернуть в колбек не сложно. в питоне для cps есть yield. (говорят в какой-то реализации яваскрипта тоже есть). для обработки ошибок нужно вместе с каждым колбеком вешать errback. и если грамотно составлять эти цепочки, то в целом, жить можно. только очень сложно дебажить такую монструозную штуку на генераторах. где-то забыл поставить errback и хрен разберешься где падает.
Странно как-то это, путать асинхронность ввода/вывода с параллельностью просчетов разных.
Для асинхронности ввода/вывода всем хорош gevent -- пропатч сокеты/потоки/работу с файлами, создавай на каждый "обработчик" по зелёному потоку и всё тут, дальше пиши код в синхронном стиле, а тот сам будет засыпать/просыпаться и так далее.
ну а обработка файлов и прочие операции подобные -- здесь уже пул процессов-воркеров какой-то нужен, а если совсем много -- сделать через celery какой-нибудь. такое себе разделение труда. а кому нужно -- пусть слушает/ждёт завершения определенных задач.
а вы всё это на twisted в один поток делали? (вместе с парсингом и проч.) или я неправильно понял?
неточно выразился про ассинхронность. конечно речь о block/non block коде. под ассинхронной функцией понимается функция, которая не делает сразу всю свою работу и возвращает управление вызвавшей ее функции как можно быстрее. Да в один поток, конечно. И в ноде все в один поток делается.
Если почитаешь то, что написал создатель Node.JS - то да, примерно так и получается. У него не было знаний и опыта разных подходов к проектированию 24/7 сервисов, поэтому и получилось так.
Но ведь эрланг тоже примерно так устроен, нет?
Reply
Reply
Reply
2. Кафеин не скрывает сложность модели выполнения Node.JS: всё равно нужно помнить, где восклицательные знаки расставлять. А если вдруг забыл - то всё заблокируется напрочь. Нельзя пропустить _ни одного_ восклицательного знака. Во всех тысячах строчек кода. Иначе именно этот пропущенный знак когда-нибудь выстрелит.
Reply
Reply
Я действительно допустил небрежность в объяснении. Не только восклицательные знаки нужно расставлять, но и избегать синхронных вызовов надо. То есть, ни одна функция, теоретически, не может быть безопасной для соседних потоков. Частью эта проблема решается соглашением о наименовании. Фольклором! А не особенностями VM, которые принципиально не допускают блокировки.
Кроме того, даже использование асинхронных функций сопряжено с граблями!
Например, потерянный коллбек блокировки даст неопределённый порядок применения операций:
node.fs.rename("/tmp/hello", "/tmp/world");
node.fs.stat("/tmp/world", function (status, stats) { ... });Вот здесь stat может выполниться раньше, чем завершится операция rename ( ... )
Reply
Кроме этих функций блокироваться практически больше нечему, если самому вечный цикл не написать. Никакого sleep(), например, нету. Поэтому, как правило, если процессор чем-нибудь занят то он занят полезной работой, а не читает тупо один и тот же адрес в памяти ради синхронизации потоков. Думаю, именно это имеется ввиду когда говорят "because nothing blocks".
Reply
штука в том, что каждая пользовательская функция/метод синхронна по умолчанию.
в смысле: файл-то он прочитает ассинхронно, но нужно, ведь, не только прочитать, но и распарсить, к примеру. а в такие штуки ассинхронность приходится руками засовывать. в какой-то момент говорить: "стоп - пускай теперь другие поработают". завернуть в колбек не сложно. в питоне для cps есть yield. (говорят в какой-то реализации яваскрипта тоже есть). для обработки ошибок нужно вместе с каждым колбеком вешать errback. и если грамотно составлять эти цепочки, то в целом, жить можно.
только очень сложно дебажить такую монструозную штуку на генераторах. где-то забыл поставить errback и хрен разберешься где падает.
Reply
Для асинхронности ввода/вывода всем хорош gevent -- пропатч сокеты/потоки/работу с файлами, создавай на каждый "обработчик" по зелёному потоку и всё тут, дальше пиши код в синхронном стиле, а тот сам будет засыпать/просыпаться и так далее.
ну а обработка файлов и прочие операции подобные -- здесь уже пул процессов-воркеров какой-то нужен, а если совсем много -- сделать через celery какой-нибудь. такое себе разделение труда. а кому нужно -- пусть слушает/ждёт завершения определенных задач.
а вы всё это на twisted в один поток делали? (вместе с парсингом и проч.) или я неправильно понял?
Reply
конечно речь о block/non block коде.
под ассинхронной функцией понимается функция, которая не делает сразу всю свою работу и возвращает управление вызвавшей ее функции как можно быстрее.
Да в один поток, конечно.
И в ноде все в один поток делается.
Reply
Reply
V = http:call(),
Z = ldap:call(V),
http:call(Z).
Reply
Reply
Reply
Reply
К сожалению, это надолго.
Reply
Leave a comment