我正在学习rxjs,并且很难绕过这两行代码:
const dispatcher = fn => (...args) => appState.next(fn(...args));
const actionX = dispatcher(data =>({type: 'X', data}));
至少部分我不明白的原因是它使用的是我还不习惯的速记语法。我一直在努力扩展它,以确切了解发生了什么,但避风港能够正确地做到这一点。例如,actionX调用dispatcher并且函数作为参数传递,但实际上是否运行直到在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}));
actionX('some data');
此代码记录下来:
>{todos: Array(0)}
>{type: "X", data: "some data"}
答案 0 :(得分:1)
一旦删除了简写方法结构,这将是代码
function foo1(data){
return {type: 'X', data}
}
function dispatcher(fn){ //fn = {type:'X', data}
function foo2(...args){
return appState.next(fn(...args));
};
return foo2;
}
const actionX = dispatcher(foo1);
actionX('something')'
希望这能让你更好地理解。
答案 1 :(得分:1)
没有arrow functions(=>
),rest parameters(...args) => {}
)和spread syntax(appState.next(fn(...args))
)的更经典的JS方法:
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
中的下一个值。如果没有这个,你需要记住每次都将你的值从回调推回到你的app状态。
换句话说,不使用此模式,上面的代码将是:
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');
在函数式编程中,有higher order functions的概念。该链接将其定义为:
高阶函数是一个函数,可以将另一个函数作为参数,或者返回一个函数作为结果。
这通常是为了减少重复并使您的应用程序更具可组合性,以减少需要编写的代码。使用这种理念,我们可以进一步改进上面的代码。我们可以提供一个检索状态并返回一个函数的函数,而不必检索状态并将其传递给调度程序函数,这样就可以多次执行此代码(因为我们可以保留对返回函数的引用)
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');