Более классический подход JS без функций со стрелками (=>
), остальные параметры (...args) => {}
) и синтаксис расширения (appState.next(fn(...args))
) для:
const dispatcher = fn => (...args) => appState.next(fn(...args));
будет:
const dispatcher = function (fn) {
return function () {
// arguments are the parameters passed to the function
const result = fn.apply(null, arguments);
return appState.next(result);
};
};
Точка этого кода, кажется, заключает в себе ваш обратный вызов (fn
), переданный в dispatcher(...)
, так что appState
обновляется с результатом обратного вызова.Это облегчает повторное использование функциональности выполнения некоторого кода и установки его в качестве следующего значения в вашем appState
.Без этого вам нужно было бы не забывать каждый раз возвращать ваше значение из обратного вызова в состояние вашего приложения.
Другими словами, без использования этого шаблона ваш код выше будет:
import Rx from 'rxjs/Rx';
const inputEl = document.querySelector('input');
const activeEl = document.querySelector('#active');
const doneEl = document.querySelector('done');
const appState = new Rx.BehaviorSubject({todos: []});
appState.subscribe(console.log);
//const dispatcher = fn => (...args) => appState.next(fn(...args));
//const actionX = dispatcher(data => ({type: 'X', data}));
const actionX = function (data) {
appState.next({type: 'X', data: data});
};
actionX('some data');
Это может быть полезно для случая, когда у вас есть одно действие, но как быть, если у вас есть несколько?Вы будете дублировать appState.next(...)
для каждого из действий.Что, если отправка результата вашего обратного вызова будет более сложной?Ну, это намного больше дублирования и возможности ошибок и не синхронизированы друг с другом.Это звучит как хорошее использование функционального программирования и превращение его в функцию многократного использования:
import Rx from 'rxjs/Rx';
const inputEl = document.querySelector('input');
const activeEl = document.querySelector('#active');
const doneEl = document.querySelector('done');
const appState = new Rx.BehaviorSubject({todos: []});
appState.subscribe(console.log);
//const dispatcher = fn => (...args) => appState.next(fn(...args));
//const actionX = dispatcher(data => ({type: 'X', data}));
const dispatcher = function (state) {
appState.next(state);
};
// or for a shorter modern version:
// const dispatcher = state => appState.next(state);
const actionX = function (data) {
dispatcher({type: 'X', data: data});
};
actionX('some data');
В функциональном программировании существует концепция функций более высокого порядка .Эта ссылка определяет это как:
Функция более высокого порядка - это функция, которая может принимать другую функцию в качестве аргумента или которая возвращает функцию в качестве результата.
Обычно это делается для того, чтобы уменьшить количество повторений и сделать ваше приложение более компонуемым, чтобы уменьшить объем кода, который необходимо написать.Используя эту философию, мы можем еще больше улучшить код вышеВместо того, чтобы извлекать состояние и передавать его в функцию диспетчера, мы можем предоставить функцию, которая извлекает состояние и возвращает функцию, чтобы этот код мог выполняться много раз (поскольку мы можем удерживать ссылку на эту возвращенную функцию).
import Rx from 'rxjs/Rx';
const inputEl = document.querySelector('input');
const activeEl = document.querySelector('#active');
const doneEl = document.querySelector('done');
const appState = new Rx.BehaviorSubject({todos: []});
appState.subscribe(console.log);
//const dispatcher = fn => (...args) => appState.next(fn(...args));
//const actionX = dispatcher(data => ({type: 'X', data}));
const dispatcher = function (fn) {
return function () {
// arguments are the parameters passed to the function
const result = fn.apply(null, arguments);
return appState.next(result);
};
};
const actionX = dispatcher(function (data) {
return {type: 'X', data: data});
});
actionX('some data');
Используя современный JS для упрощения всего этого кода, вы получите то, что у вас было:
import Rx from 'rxjs/Rx';
const inputEl = document.querySelector('input');
const activeEl = document.querySelector('#active');
const doneEl = document.querySelector('done');
const appState = new Rx.BehaviorSubject({todos: []});
appState.subscribe(console.log);
const dispatcher = fn => (...args) => appState.next(fn(...args));
//const dispatcher = function (fn) {
// return function () {
// // arguments are the parameters passed to the function
// const result = fn.apply(null, arguments);
// return appState.next(result);
// };
//};
const actionX = dispatcher(data => ({type: 'X', data}));
//const actionX = dispatcher(function (data) {
// return {type: 'X', data: data});
//});
actionX('some data');