Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ns.Events] Неверно работает ns.Events.once #607

Merged
merged 1 commit into from
Jul 14, 2016

Conversation

iEgit
Copy link
Collaborator

@iEgit iEgit commented Jul 6, 2016

ns.events.off не отписывает once события.
Пример

const say = () => console.log('yo')
ns.events.once('yo', say)
ns.events.off('yo', say)
ns.events.trigger('yo')

// says 'yo'

Добавил ссылку на оригинальный обработчик и поправил off.

@iEgit
Copy link
Collaborator Author

iEgit commented Jul 6, 2016

@vitkarpov @i2r

@vitkarpov vitkarpov changed the title fixed ns.events.once [ns.Events] Неверно работает ns.Events.once Jul 6, 2016
@vitkarpov
Copy link
Member

@chestozo @Katochimoto

@vitkarpov vitkarpov added this to the 0.8.6 milestone Jul 6, 2016
var that = this;
var once = function() {
that.off( name, once );
handler.apply(this, arguments);
};
this.on( name, once );
once.__original = handler;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне кажется, что при отписке необходимо затирать эту ссылку:

once.__original = null;

а то создадим утечку памяти

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

где-то в районе splice в off

Copy link
Collaborator Author

@iEgit iEgit Jul 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не думаю.
Исходная функция не уйдёт раньше, чем once, так как на неё будет как минимум одна актуальная ссылка. Если она нигде больше не нужна, то она уйдет в следующем событии вместе с once. Если нужна, то просто будет меньше на одну ссылку на неё (так как уйдет once).

@vitkarpov
Copy link
Member

👍

@chestozo
Copy link
Member

chestozo commented Jul 6, 2016

Круто, но для полноты надо поддержать двойной .once(), кажется, сейчас будут проблемы с перезатиранием __original.

@alexeyten
Copy link
Contributor

alexeyten commented Jul 7, 2016

С двойным once проблемы нет. Есть спецэффекты если я одну и ту же функцию добавлю через on и once, а потом вызову off на неё один раз. Удалится первая из добавленных функций, это может быть неожиданно.

@vitkarpov vitkarpov added the bug label Jul 7, 2016
@iEgit
Copy link
Collaborator Author

iEgit commented Jul 7, 2016

@chestozo проблемы не будет.
Поговорили с @alexeyten, есть такая проблема.

const say = () => console.log('yo')
ns.events.once('yo', say)
ns.events.on('yo', say)
ns.events.off('yo', say) // снимет обработчик once, а не on

Cошлись на том, что с этим можно жить и достаточно описать эту особенность в документации.

Что думаете?

@vitkarpov
Copy link
Member

А какое поведение ожидаемое в данном случае? Кажется, что должен снять оба обработчика, да?

@alexeyten
Copy link
Contributor

@vitkarpov в том-то и дело, что любое будет неожиданным. Раньше .off снимал первый .on, но они все были одинаковые так что не было особенных проблем.

А вообще я с трудом представляю зачем может быть надо добавать одну и ту же функцию дважды.

@vitkarpov
Copy link
Member

Ну, т.е. такой ситуации, как ты описал, по идее, не должно быть?

@vitkarpov
Copy link
Member

В реальной жизни

@iEgit iEgit self-assigned this Jul 7, 2016
@alexeyten
Copy link
Contributor

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

@alexeyten
Copy link
Contributor

alexeyten commented Jul 7, 2016

UPD: а, нет, не будет

@vitkarpov
Copy link
Member

Ну и ок 👍

@alexeyten
Copy link
Contributor

👍

@chestozo
Copy link
Member

chestozo commented Jul 8, 2016

@alexeyten

А вообще я с трудом представляю зачем может быть надо добавать одну и ту же функцию дважды.

к примеру, по ошибке
предлагаю в on() и в once() делать проверку и кидать warning, к примеру

@iEgit:
Давай добавим тестов на:

  • двойной once()
  • once() + off() при этом off(eventName) и off(eventName, foo)

@alexeyten
Copy link
Contributor

alexeyten commented Jul 8, 2016

предлагаю в on() и в once() делать проверку и кидать warning, к примеру

Если только в DEV-сборке (как react и т.п.)

@vitkarpov
Copy link
Member

Если только в DEV-сборке (как react и т.п.)

Есть ns.log.error — он как раз так и работает

@vitkarpov
Copy link
Member

@iEgit ping? поправишь по комментариям, докинешь тестов:

  • двойной once()
  • once() + off()
  • off(eventName) и off(eventName, foo)

@iEgit
Copy link
Collaborator Author

iEgit commented Jul 11, 2016

да, доделаю

@iEgit
Copy link
Collaborator Author

iEgit commented Jul 11, 2016

предлагаю в on() и в once() делать проверку и кидать warning, к примеру

А на что проверку? На то, что уже есть такой обработчик где-то?

@iEgit iEgit force-pushed the events-once-fix branch from 4f692f9 to a2917b0 Compare July 11, 2016 17:48
@iEgit
Copy link
Collaborator Author

iEgit commented Jul 11, 2016

тесты добавил

@vitkarpov
Copy link
Member

👍 @chestozo ?

// Нашли и удаляем этот обработчик.
handlers.splice(i, 1);
break;
}
Copy link
Member

@chestozo chestozo Jul 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Т.е. такие нельзя два раза навесить один и тот же обработчик?
Мне кажется, надо делать как в jquery, а там можно:

var $body = $(document.body);
var handler = function() {
    console.log(+new Date());
};

$body.one('click', handler);
$body.one('click', handler);

$body.trigger('click');
// 1468415760081
// 1468415760082

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

оу, кул ) 👍

@chestozo
Copy link
Member

А какое поведение ожидаемое в данном случае? Кажется, что должен снять оба обработчика, да?

Я думаю мы ориентируемся на jquery.
Там поведение такое - оба обработчика будут отписаны:

var $body = $(document.body);
var handler = function() {
    console.log(+new Date());
};

$body.one('click', handler);
$body.on('click', handler);

$body.off('click', handler);

$body.trigger('click');
// Ничего не происходит

@chestozo
Copy link
Member

Может допилим до поведения "как в jquery"?

@iEgit
Copy link
Collaborator Author

iEgit commented Jul 13, 2016

А ты уверен, что нужно ориентироваться на эту великую технологию?

@vitkarpov
Copy link
Member

vitkarpov commented Jul 13, 2016

Там поведение такое - оба обработчика будут отписаны

Вообще, кажется, логичным чтобы once и on в этом смысле работали одинаково, за тем лишь исключением, что once один раз выполнится.

Т.е. должно быть аналогично случаю:

foo.on('event', handler);
foo.on('event', handler);

foo.off('event', handler);

Сейчас это не так?

@chestozo
Copy link
Member

А ты уверен, что нужно ориентироваться на эту великую технологию?

Пока используется jquery - лучше бы поведение наших эвентов было бы максимально аналогичным.

Сейчас это не так?

А я не знаю, давайте напишем тест :)

@vitkarpov
Copy link
Member

vitkarpov commented Jul 13, 2016

А я не знаю, давайте напишем тест :)

https://github.com/yandex-ui/noscript/pull/607/files/a2917b0895c83c97132382849dd15099b23e680a#diff-99f6436afe06f3898363ed5e9798b602R144 — а вот есть тест на двойной once и off.

Работает консистентно с текущим поведением on:

  • подписали дважды один и тот же обработчик
  • сделали off
  • убрался первый обработчик

Они сейчас все хранятся в одном массиве плоским списком, как только нашли первый handler, то удаляем его из массива и делаем break.

Мы не можем сделать поведение как в jquery, мы должны сделать как в ns.Events :)

@chestozo
Copy link
Member

Поговорили голосом - завёл #613
По этой issue 👍 :)

@vitkarpov vitkarpov merged commit ced85b2 into master Jul 14, 2016
@vitkarpov vitkarpov deleted the events-once-fix branch July 14, 2016 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants