【发布时间】:2018-07-20 13:48:31
【问题描述】:
我正在将一些旧节点模块重构为更实用的样式。当谈到 FP 时,我就像是二年级新生 :) 我一直挂断的地方是处理大型异步流。这是我向数据库发出请求然后缓存响应的示例:
// Some external xhr/promise lib
const fetchFromDb = make => {
return new Promise(resolve => {
console.log('Simulate async db request...'); // just simulating a async request/response here.
setTimeout(() => {
console.log('Simulate db response...');
resolve({ make: 'toyota', data: 'stuff' });
}, 100);
});
};
// memoized fn
// this caches the response to getCarData(x) so that whenever it is invoked with 'x' again, the same response gets returned.
const getCarData = R.memoizeWith(R.identity, (carMake, response) => response.data);
// Is this function pure? Or is it setting something outside the scope (i.e., getCarData)?
const getCarDataFromDb = (carMake) => {
return fetchFromDb(carMake).then(getCarData.bind(null, carMake));
// Note: This return statement is essentially the same as:
// return fetchFromDb(carMake).then(result => getCarData(carMake, result));
};
// Initialize the request for 'toyota' data
const toyota = getCarDataFromDb('toyota'); // must be called no matter what
// Approach #1 - Just rely on thenable
console.log(`Value of toyota is: ${toyota.toString()}`);
toyota.then(d => console.log(`Value in thenable: ${d}`)); // -> Value in thenable: stuff
// Approach #2 - Just make sure you do not call this fn before db response.
setTimeout(() => {
const car = getCarData('toyota'); // so nice!
console.log(`later, car is: ${car}`); // -> 'later, car is: stuff'
}, 200);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
我真的很喜欢 memoization 用于缓存大型 JSON 对象和其他计算属性。但是对于很多异步请求,它们的响应相互依赖才能完成工作,我无法跟踪我拥有的信息和时间。我想避免大量使用 Promise 来管理流程。它是一个节点应用程序,因此使事情同步以确保可用性会阻塞事件循环并真正影响性能。
我更喜欢方法#2,我可以通过getCarData('toyota') 简单地获取汽车数据。但缺点是我必须确保响应已经返回。对于方法#1,我总是必须使用thenable,它可以缓解方法#2 的问题,但会引入它自己的问题。
问题:
-
getCarFromDb是上面写的纯函数吗?如果不是,那怎么不是副作用? - 以这种方式使用记忆是 FP 反模式吗?也就是说,从带有响应的 thenable 调用它,以便将来对同一方法的调用返回缓存的值?
【问题讨论】:
-
为什么我们不使用when then函数?
-
getCarFromDb 是上面写的纯函数吗?" 不是。任何访问 I/O 的东西都是不纯的。
标签: javascript node.js asynchronous functional-programming ramda.js