I am building an ad-hoc text-editor. I have two functions which use a cache, `provideHover` and `provideCompletionItems`. ``` "use strict"; import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; const $ = require("jquery"); const urlResolve = require("url-resolve"); const AUTOCOMPLETE_ENDPOINT = "http://localhost:7000/"; const LRU = require("lru-cache"); const options = { max: 500, length: (suggestions, key) => { return suggestions.length } }; const cache = new LRU(options); const definition_cache = new LRU(options); (function () { // create div to avoid needing a HtmlWebpackPlugin template const div = document.createElement('div'); div.id = 'root'; div.style = 'width:800px; height:600px; border:1px solid #ccc;'; document.body.appendChild(div); })(); monaco.editor.create( document.getElementById('root'), { value: ``, language: 'python', theme: 'vs-dark' } ); const getCompletions = (text) => { return $.ajax({ url: urlResolve(AUTOCOMPLETE_ENDPOINT, "suggestion"), type: 'GET', "data": { "text": text } }); }; const getDocumentation = (cursorInfo) => { const line = cursorInfo.line; const column = cursorInfo.column; const text = cursorInfo.text; return $.ajax({ url: urlResolve(AUTOCOMPLETE_ENDPOINT, "documentation"), type: 'GET', "data": { "line": line, "column": column, "text": text, "highlighted": cursorInfo.highlighted } }); } monaco.languages.registerHoverProvider("python", { provideHover: async (model, position) => { const lineNumber = position.lineNumber; const snippet = model.getWordAtPosition(position); const text = model.getValueInRange({ startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: snippet.endColumn }); if (definition_cache.has(text)) { console.log("hit"); return { contents: [{ value: definition_cache.get(text) }] } } const response = await getDocumentation({ "line": lineNumber, "column": snippet.endColumn, "text": text, "highlighted": snippet.word }); definition_cache.set(text, response.documentation); return { contents: [{ value: response.documentation }] } } }); monaco.languages.registerCompletionItemProvider('python', { provideCompletionItems: async (model, position) => { const text = model.getValueInRange({ startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column }); if (cache.has(text)) { const suggestions = cache.get(text); return { "suggestions": suggestions }; } const completions = await getCompletions(text) const suggestions = completions.map(c => ({ label: c.name, insertText: c.name })); cache.set(text, suggestions) return { "suggestions": suggestions }; } }); ``` As it stands, the introduction of the cache makes the code quite ugly (in my opinion). I'd like to refactor it so that I have only one cache usage that applies in both situations -- something like a Python decorator. How do I make the code cleaner?