[personal profile] sassa_nf
http://stackoverflow.com/q/36956220/1935631

It looks like the people don't even understand the meaning of the question.

Is there a safe pattern / good practice / guarantee by design on the arrival and observation of events?

$ cat a.js
'use strict';

const EventEmitter = require('events');

const e = new EventEmitter();
e.on('a', x => {
  console.log('x = ' + x);
  if (x === 0) {
    e.emit('a', 2);
    e.removeAllListeners('a');
    e.emit('a', 3);
    e.on('a', y => console.log('y = ' + y));
    e.emit('a', 4);
  }
});

e.on('a', z => console.log('z = ' + z));

console.log('a');
e.emit('a', 0);
console.log('b');
e.emit('a', 1);
console.log('c');

$ node a.js 
a
x = 0
x = 2
z = 2
y = 4
z = 0
b
y = 1
c



  • emit is atomic with respect to remove* and add* listeners
  • emits are not atomic with respect to each other
  • As a result, consumers can't agree on the observed order of events: x=0,x=2, but z=2,z=0 - but what's the way to make them agree? The only guarantee I can see is program order of emit start with respect to emit end (ie make all emits occur in a single place)

Date: 2016-05-01 03:01 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
But tcp works ok (on most occasions).

Date: 2016-05-01 03:43 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
У тебя в вопросе на SO пример другой же, на какой из вопросов отвечать? И там не "the people", а один-единственный дебил mscdex. В "попсовых" разделах много дебилов с репутацией, поскольку попредлагали 100500 кривых решений для простых вопросов, и они прокатили.

На вопрос в посте ответ такой: EventEmitter нереентрабельный, если ты удаляешь обработчик из обработчика, или вызываешь emit - то получаешь по голове unspecified behaviour. Вылазят наружу детали реализации эмиттера.

Заключи всю ветку эмитирования в process.nextTick и посмотри, должно помочь.

Т.е. if (x == 0) process.nextTick(() => { ... })
Edited Date: 2016-05-01 03:47 pm (UTC)

Date: 2016-05-01 04:08 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Ещё небольшой оффтоп:

console.log логирует все свои аргументы, т.е. вместо плюса нужна запятая:

console.log('y =', y)

Я вообще вместо этого юзаю объектные литералы:

console.log({ y : y })

Если нужно составную строку писать - console.log умеет работать как printf, т.е. "y = %s", y

Date: 2016-05-01 05:53 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Кто-то из "the people" даже -1 успел притулить :-) как будто вопрос тупой.

Да, на SO вопрос сформулирован по-другому, т.к. хотелось привязать к реалу. Вот у нас есть обработчик connect, есть обработчик error, есть обработчик timeout. Нужны гарантии, что они взаимоисключают друг друга, т.к. при каких-то раскладах я наблюдал, что error вызывался на старом списке обработчиков, а там обработчик только ошибок соединения. Не исключено, что там был хитрый случай (например, кто-то что-то хотел засунуть в логгер, логгер полез к моему сокету, а тот уже error в неподходящий момент), но хотелось как раз послушать о гарантиях от собственно EventEmitter и какие подходы считаются работающими по спецификации (хахаха), а какие подсказаны практикой.

Да, nextTick, по-видимому, должен помочь. emit в себе асинхрона не содержит, так что, можно построить synchronization order, в котором все event handlers начинаются в одном тике, и тогда process.nextTick(...) гарантированно после начала event handlers.

Date: 2016-05-01 05:54 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Да, спасибо.

Date: 2016-05-01 05:57 pm (UTC)
From: [identity profile] nponeccop.livejournal.com
Не надо там особо строить этот order

EventEmitter.emit - это просто handlers.forEach(x => x(args))

Соответственно чтобы всё было в порядке, достаточно делать "рекурсивные" вызовы в отдельном тике. Оно сразу полечится.

"Правильное" решение - это написать изначально устойчивый EventEmitter. Но поменять эмиттер в составе ноды не удастся, там придётся юзать этот трюк "вызывать эмит рекурсивно только на следующем тике", либо сделать декоратор.

Date: 2016-05-01 05:59 pm (UTC)
From: [identity profile] sassa-nf.livejournal.com
Yes. The problem is people didn't think about consistency and guarantees, as if synchronization orders, TLA and π-calculus were not invented yet.

Date: 2016-05-01 06:01 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
Almost everybody is totally clueless, I think.
Page generated May. 22nd, 2026 03:13 am
Powered by Dreamwidth Studios