ES6 Proxy: установить ловушку свойства с помощью debounce, можно ли избежать словаря обратных вызовов?

Цель: получить любое измененное поле формы в виде пары «имя-значение» при вводе пользователем с устранением дребезга при вводе. Образец шаблона (человек — модель с двусторонней привязкой).

<form>
  <q-input v-model="person.familyName" />
  <q-input v-model="person.givenName" />
  ...
</form>

Я заставил его работать с прокси-сервером ES6, но, похоже, есть запах кода со словарем обратных вызовов для устранения дребезга: каждое свойство помещает собственный обратный вызов в словарь, чтобы не мешать другим полям.

// callback per 'field name' to prevent from skipping changes
// while fast typing with Tab button to switch between fields.
const debounces: { [key: string]: (...args: any[]) => any } = {};

const person = new Proxy(someSourceModel, {
    set: (target, key: string, value, receiver) => {
        Reflect.set(target, key, value, receiver);

        if (!debounces[key])
            debounces[key] = debounce(300, (key, value) => // throttle-debounce lib
            {
                // Do anything with changed key-value pair.
                // For example, send it with update to Dexie/PouchDB as
                // single field instead of whole object.
                console.log(`${String(key)}: ${String(value)}`);

                delete debounces[key]; // Cleanup when it fired.
            });

        debounces[key](key, value); // Fire it!
        return true;
    }
});

Есть ли способ избежать словаря обратных вызовов?

пример включен.


person Arsync    schedule 21.11.2020    source источник


Ответы (1)


Возможное решение с lodash-es/debounce: немедленный вызов 'flush' ожидающего устранения дребезга при изменении другого свойства.

let lastProperty: string;

const onChanged = debounce((key, value) => {
    // Do anything with changed key-value pair.
    // For example, send it with update to Dexie/PouchDB.
    console.log(`${String(key)}: ${String(value)}`);
}, 300);

const person = new Proxy(someSourceModel, {
    set: (target, key: string, value, receiver) => {
        Reflect.set(target, key, value, receiver);

        if (lastProperty != key) {
            lastProperty = key;
            onChanged.flush();
        }

        onChanged(key, value);
        return true;
    }
});

Codesandbox пример

person Arsync    schedule 22.11.2020