Ad

You have acess to remote data using a function named getData, but you have to pay royalties each time you call it.

You know the data doesn't change in time, but depends on the arguments you're passing to getData

getData('some', 'args') // returns some data
getData('some', 'other') // returns another data

write a function multiMemoize that tankes a function, here getData, as an argument and returns an extended version of this function.

The extended version only calls the original function once for given arguments, then returns memoized result if called with the same arguments, like this :

let memoized = multiMemoize(getData)

let res1 = memoized('hello', 'world') 
// getData is called

let res2 = memoized('hello', 'world')
// getData is NOT called

res1 === res2 // true

let other1 = memoized('fizz', 'buzz')
// getData is called

let res3 = memoized('hello', 'world')
// getData is NOT called

res3 === res1 // true

// getData was called only 2 times

Constraints

  • The multiMemoizeFunction should extend any function whatever the number of arguments

  • the extended version should accept any arguments, strings, integer, objects... beware that random tests use random characters

  • it should work properly with promises (you have preloaded function getDataAsync to test that):

let asyncMemoized = multiMemoize(getDataAsync)

asyncMemoized(5)
  .then(data => console.log(data))
  .catch(err => console.log(err))

asyncMemoized(5)
  .then(data => console.log(data))
  .catch(err => console.log(err))
// gives the same result (immediately)
// WITHOUT calling getDataAsync

helpers

  • you have function getData to fetch the data synchonously

  • you have function getDataAsync to fetch it in a promise that resolves in ~1 second

  • you can call getRequestCount to follow how many times you called each function :

getRequestCount() === {
  sync: 5,
  async: 2,
  total: 7
}
// or
getRequestCount().sync === 5

  • if you want to deal with multiple datasources, you can create another one using the class DataSource which exposes methods getData, getDataSync & getRequestCount :
let dataSource2 = new DataSource()

dataSource2.getDataAsync()
dataSource2.getDataAsync()

dataSource2.getRequestCount().async === 2

``
function multiMemoize (func) {
  let cache = new Map()
  
  function run (...args) {
    let key = JSON.stringify(args)
    let cached = cache.get(key)
    if (cached !== undefined) {
      return cached
    } else {
      let value = func(...args)
      cache.set(key, value)
      return value
    }
  }
  return run
}
/*
let memoized = multiMemoize(getData)

let res1 = memoized('hello', 'world') 
// getData is called

let res2 = memoized('hello', 'world')
// getData is NOT called

res1 === res2 // true

let other1 = memoized('fizz', 'buzz')
// getData is called

let res3 = memoized('hello', 'world')
// getData is NOT called

res3 === res1 // true

console.log(getRequestCount())
*/