JavaScript: два интересных сниппета
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)
})
При нажатии кнопки значение счетчика увеличивается на единицу. Это приводит к обновлению текста кнопки.
Таким образом, код работает, как ожидается. Но… почему? Как это работает?