opt.type opt.id opt.tardy opt.tardy_timeout
function cached(opt) {
  if (typeof opt == 'undefined' || opt === null) opt = {};
  if (typeof opt == 'string') opt = {type:opt};
  if (typeof opt.id != 'string') opt.id = _random_string(8);
  opt = Object.assign({}, getSettings(), opt);
  for (var i in opt) checkSetting(i, opt[i]);

  return function (func, key, descriptor) {
    if (key) func = func[key]; //for ES6 notation

    const f = function (...rest) {
      const _key = _hash(rest, opt.id);
      return cacheObj.get(opt, _key)
              .then(res => {
                if (typeof res == 'undefined' || res === null) {  
                  res = _update.bind(this)(opt, func, rest);
                }
                return res;
              });
    }
    f.forceUpdate = function(...rest){
      _update.bind(this, opt, func)(rest)
    }

    if (key) {
      //ES6 notation
      descriptor.value = f;
    } else {
      //vanilla js notation
      return f;
    }
  }
}