Javascript 函数以更有效地处理并发异步函数

Javascript function to handle concurrent async function more efficiently

考虑以下几点:

我想要 create/use 某种通用的 method/class 来包装业务逻辑承诺方法。这个通用 method/call 将知道何时调用实际的业务逻辑函数,何时等待飞行中完成,然后在有响应时解决所有等待的调用。

我希望已经有一个节点模块可以做到这一点,但想不出这种类型的实用程序会被称为什么。

类似于 lodash throttle/debounce,但不完全相同。

如果它不存在我可以自己写,但是很难为它想出一个合理的名字。

如有任何帮助,我们将不胜感激。

Web 应用程序只能有 6 个并发请求,因为这是浏览器的硬性限制。较旧的 IE 只能做 2。所以无论你做什么 - 这是一个硬性限制。

一般情况下应该在服务端解决多路复用

现在 - 对于您的实际问题 - 您要求的那种缓存对于承诺来说非常简单。

function once(fn) {
    var val = null; // cache starts as empty
    return () => val || (val = fn()); // return value or set it.
}


var get = once(getData);
get();
get(); // same call, even though the value didn't change.

现在,您可能想要添加一个过期政策:

function once(fn, timeout) {
  var val = null, timer = null; // cache starts as empty
  return () => val || (val = fn().tap(invalidate)); // return value and invalidate
  function invalidate() { 
    clearTimeout(timer); // remove timer.
    timer = setTimeout(() => val = null, timeout);
  }
}

var get = once(getData, 10000); 

如果失败,您可能还想取消缓存结果:

function once(fn, timeout) {
  var val = null, timer = null; // cache starts as empty
  return () => val || 
   (val = fn().catch(e => value = null, Promise.reject(e)).tap(invalidate));
  function invalidate() { 
    clearTimeout(timer); // remove timer.
    timer = setTimeout(() => val = null, timeout);
  }
}

由于原始功能是一行代码,因此没有帮助程序。

您可以实现 PromiseCaching,例如:

module.exports = function request(url) {
    if (caches[url]) return caches[url];
    var promise = req(url);

    return (caches[url] = promise);
};

var req = require('');
var caches = {};

编辑:

让我更详细地解释一下:

这里不是关于响应的缓存,而是关于承诺的缓存。 Nodejs 是单线程的,这意味着没有并发函数调用,即使一切都是异步的,在一个时间点,也只运行一段代码。这意味着,会有人首先使用 url y.com/foo 调用该函数,缓存中不会有任何承诺,因此它将触发 GET 请求并缓存 return承诺。当有人立即使用相同的 url 调用该函数时,不会触发更多请求,而是针对此 url 的第一个承诺将被 returned,消费者可以订阅 done/fail 回调。 当响应准备好并且承诺得到履行时,有人使用相同的 url 发出请求,然后再次,它会取回已经准备好的缓存承诺。

Promise 缓存 是防止重复异步任务的好技术。

您可以使用 promise 来防止同时请求重复

用nodejs写的例子,浏览器也可以用这个模式

const rp = require('request-promise'), 
var wait = null; 

function getUser(req, rep, next){
  function userSuccess(){
    wait = null;
  };
  function userErr(){
    wait = null;
  };

  if (wait){
    console.log('a wait');
  }
  else{
    wait = rp.get({ url: config.API_FLIX + "/menu"});
  }

  wait.then(userSuccess).catch(userErr);
}