JavaScript: два интересных сниппета

mapolvqq4uunxfqoaviv3g9km9y.jpeg


Hello, world!

В этой небольшой заметке я хочу поделиться с вами двумя сниппетами, которые показались мне очень интересными. Первый сниппет представляет собой пример реализации простой реактивности (signal), второй — способ предотвращения несогласованности данных в результате состояния гонки (race condition). Первая конструкция используется в SolidJS (с некоторыми дополнительными оптимизациями), вторая — заимствована из одного рабочего проекта.

Интересно? Тогда прошу под кат.

Начнем с сигнала.

Взгляните на следующий код:

let currentListener

function createSignal(initialValue) {
  let value = initialValue
  const subscribers = new Set()

  const read = () => {
    if (currentListener) {
      subscribers.add(currentListener)
    }
    return value
  }

  const write = (newValue) => {
    value = newValue
    subscribers.forEach((fn) => fn())
  }

  return [read, write]
}

function createEffect(callback) {
  currentListener = callback
  callback()
  currentListener = null
}

Функция createSignal создает «реактивное» значение, а функция createEffect принимает коллбэк, который выполняется при изменении этого значения.

Пример использования данного сниппета:

const [count, setCount] = createSignal(0)

const button = document.querySelector('button')

createEffect(() => {
  button.textContent = count()
})

button.addEventListener('click', () => {
  setCount(count() + 1)
})

При нажатии кнопки значение счетчика увеличивается на единицу. Это приводит к обновлению текста кнопки.

Таким образом, код работает, как ожидается. Но… почему? Как это работает?

© Habrahabr.ru