cellx
cellx copied to clipboard
pull в ICellOptions
сейчас конструктор Cell такой:
constructor(value?: T, opts?: ICellOptions<T>);
constructor(pull: ICellPull, opts?: ICellOptions<T>);
На мой взгляд правильнее добавить pull в ICellOptions, тем более что там уже есть put, reap и т.д.
interface ICellOptions<T> {
pull: (push: (value: any) => void, fail: (err: any) => void, oldValue: any): any;
...
Тогда и неаккуратность с oldValue === undefined при первом выполнении pull разрешится:
cellx(1, {
pull(push, fail, oldValue) {
}
})
Да и в принципе oldValue в pull не нужен вроде в таком случае.
Есть еще один аспект, например когда pull функция генерируется кем-то, можно не генерить функции, а экземпляр класса создать, ресурсов меньше.
pull прийдётся постоянно заворачивать в { pull: /* ... */ }
, неудобно.
Да и в принципе oldValue в pull не нужен вроде в таком случае.
через oldValue можно управлять какое значение будет иметь асинхронная ячейка во время запроса:
var value = cellx((push, fail, oldValue) => {
makeRequest(res => {
push(res.data.value);
});
return oldValue; // на время запроса ячейка останется со старым значением
return oldValue || 0; // на время запроса ячейка останется со старым значением и значение до первого ответа будет `0`.
return null; // на время запроса ячейка будет обнулена.
});
Бывает не надо заворачивать { pull: /* ... */ }
, а надо new CustomCellOptions(bla-bla)
Создание объекта дешевле, чем функции.
Но где-то в bla-bla
тоже ведь функция будет?
Не факт, но надо подумать.
У меня задумка была с очередями, которые управляли бы состоянием атома:
class AsyncQeue<V> {
_defaultValue: V
pull(push, fail, oldValue) {}
push() {} ...
}
const queue = new AsyncQeue('defaut')
cellx(null, queue)
// что не делать (...args) => queue.pull(...args)
Можно писать код так, что генерации функций не будет нигде. Но я про то, что нет единообразия:
pull в ICellOptions, тем более что там уже есть put, reap и т.д.
Почему передача pull вдруг иначе, чем остальные точки расширения?
При попытке интегрироваться с cellx, это порождает вот такие костыли:
class AtomController {
_pull(push: (v: V) => void, fail: (e: Error) => void, oldValue: ?V): V {
//...
}
reap(): void {
this._updater.cancel()
}
pull: PullFn<V> = (
push: (v: V) => void,
fail: (e: Error) => void,
oldValue: ?V
) => this._pull(push, fail, oldValue)
}
const ac = new AtomController()
new cellx.Cell(ac.pull, ac)
Сравни cellxPull и cellxNoPull
Абстракции проще, когда pull/push не в формуле, а отдельно, в виде атомов.