我整夜都在努力,无法解决这个难题。 我想以功能方式重构代码:
const R = require('ramda')
const axios = require('axios')
const Datastore = require('nedb')
const getDatastore = R.always(
new Datastore({ filename: './cache.nedb', autoload: true }),
)
const writeHtmlToCache = R.curry((db, url, html) => {
return new Promise((resolve, reject) => {
db.insert({ url, html }, (err, doc) => {
if (err) return reject(err)
resolve(doc)
})
})
})
const readHtmlFromCache = R.curry((db, url) => {
return new Promise((resolve, reject) => {
db.findOne({ url }, (err, doc) => {
if (err) reject(err)
else resolve(doc)
})
})
})
const app = async url => {
const db = getDatastore()
let html = R.prop('html', await readHtmlFromCache(db, url))
if (html) {
console.log('loaded from cache', html.length)
return html
} else {
html = R.prop('data', await axios.get(url))
writeHtmlToCache(db, url, html)
console.log('loaded from web', html.length)
return html
}
}
app('http://example.org/')
我遇到的问题:
1)在writeToCache
函数中,我需要url
和html
作为将记录写入db的输入,但是如果我将此函数放在fetchHtml
之后的管道中,则只会得到{ {1}}。还有-管道中的功能应该是一元的。我应该以某种方式使对象html
传递到我的{ url: 'http...', html: '<html>...' }
中吗?
2)我想使用R.function来进行writeToCahce
的操作,或者如果那里没有成功,请从Web管道中获取内容(这也会将html保存在db中)。但是我的缓存读取功能返回Promise。我可以使用readFromCache
,但似乎不能与R.pipeP
一起使用(either
继续执行第一个函数并返回null。似乎它测试Promise本身,而且它是真实值,这给了我希望到pipeP,并在那里解析为null(缓存为空))
3)我尝试与Task monad一起玩,但没有取得很大的成功。我对这些概念还是陌生的
我觉得自己做错了什么。很好奇如何做到
答案 0 :(得分:3)
我会使用crocks中的一些辅助功能以及闭包的神奇之处
import unless from 'crocks/logic/unless'
import composeP from 'crocks/combinators/composeP'
const getDataWithUrl = url => () =>
axios.get(url).then(R.prop('data')))
const writeWithDbAndUrl = (db, url) => html =>
writeHtmlToCache(db, url, html)
const writeWhenNoHtml = (db, url) =>
composeP(writeWithDbAndUrl(db, url), getDataWithUrl(url))
const app = url => {
const db = getDatastore()
return readHtmlFromCache(db, url)
.then(unless(R.prop('html'), writeWhenNoHtml(db, url))
}