Итак, прямо сейчас в моем приложении React происходит невероятно странное явление, и я не совсем уверен, как его описать, но вот:
Я создаю синтезатор с API веб-аудио и React, который реагирует на события keyDown, чтобы вызвать начало заметки, и события keyUp, чтобы вызвать конец заметки. В большинстве случаев это работает безотказно. Но одно нажатие клавиши из каждых 10-15 приводит к срабатыванию дополнительного события keyDown после события keyUp. У меня есть компонент React, который занимается обработкой всех событий и запускает действия Redux в зависимости от обрабатываемого события (keyUp или keyDown). Кроме того, я использую метод lodash/debounce для подавления дополнительных событий keyDown, когда пользователь держит клавишу.
Я не привязан к функции lodash/debounce, мне просто нужно что-то, чтобы подавить лишние события keyDown. Вполне возможно, что я не использую его должным образом или есть более простое решение. Мне просто нужны ответы.
Мой компонент выглядит следующим образом:
import React, { Component } from 'react'
import debounce from 'lodash/debounce'
import { REGISTERED_KEYS } from '../constants/keyboard-constants'
export default class ComputerKeyboard extends Component {
constructor (props) {
super(props)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleKeyUp = this.handleKeyUp.bind(this)
}
handleKeyDown (e) {
return debounce((event = e) => {
if (this.props.currentKeys.indexOf(event.keyCode) < 0 && REGISTERED_KEYS.includes(event.keyCode)) {
this.props.keyDown(event.keyCode)
this.props.updateGateStartTime({ value: this.props.audioContext.currentTime })
}
}, 2)()
}
handleKeyUp (e) {
const isLastKey = this.props.currentKeys.includes(e.keyCode) && this.props.currentKeys.length === 1
if (isLastKey && this.props.gateStartTime) {
this.props.updateGateStartTime({ value: null })
}
if (this.props.currentKeys.includes(e.keyCode) && REGISTERED_KEYS.includes(e.keyCode)) {
this.props.keyUp(e.keyCode)
}
}
componentDidMount () {
document.addEventListener('keydown', this.handleKeyDown)
document.addEventListener('keyup', this.handleKeyUp)
}
componentWillUnmount () {
document.removeEventListener('keydown', this.handleKeyDown)
document.removeEventListener('keyup', this.handleKeyUp)
}
render () {
return null
}
}
@RandyCasburn Для этого компонента нет JSX. Он просто отображает null и помещает прослушиватели событий в document.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это был debounce. Как только я удалил это, я больше никогда не видел ошибку. Я пытался придумать, но не понимал разницы между дросселированием и устранением дребезга. В соответствии с этим статья:
Throttling enforces a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."
и
Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."
Я думаю, что я, вероятно, хочу регулировать и что, устраняя дребезг, я разрешаю последний вызов функции быть пропущенным, потому что количество времени между вызовами было достаточно коротким, чтобы иногда, после выпуска, устранение дребезга пропускало событие что не должно было быть. Кроме того, поскольку клавиша больше не нажималась и не регистрировалась как таковая, логика отказоустойчивости, встроенная в handleKeyDown, больше не была адекватной, поскольку предполагала, что на самом деле задействованы клавиши.
Давайте посмотрим на JSX.