Javascript函数更有效地处理并发异步函数
考虑以下几点:Javascript函数更有效地处理并发异步函数,javascript,node.js,promise,bluebird,Javascript,Node.js,Promise,Bluebird,考虑以下几点: 每秒最多可有100个并发请求的web应用程序 每个传入请求当前向端点发出http请求以获取一些数据(可能需要5秒) 我只想发出一次http请求,也就是说,我不想同时调用同一个端点,因为它将返回相同的数据 想法是只有第一个请求才会进行http调用以获取数据 当此呼叫为“机上”时,后续请求将不会发出相同的呼叫,而是“等待”第一个机上请求完成。 当对数据的初始http请求已响应时,它必须使用数据响应所有调用。 我使用Bluebird Promissions来实现执行http请求的异步
- 每秒最多可有100个并发请求的web应用程序
- 每个传入请求当前向端点发出http请求以获取一些数据(可能需要5秒)
- 我只想发出一次http请求,也就是说,我不想同时调用同一个端点,因为它将返回相同的数据
- 想法是只有第一个请求才会进行http调用以获取数据
- 当此呼叫为“机上”时,后续请求将不会发出相同的呼叫,而是“等待”第一个机上请求完成。
- 当对数据的初始http请求已响应时,它必须使用数据响应所有调用。
- 我使用Bluebird Promissions来实现执行http请求的异步函数。
任何帮助都将不胜感激。一个web应用程序只能有6个并发请求,因为这是硬浏览器限制。年纪大一点的人只能做两件事。因此,无论你做什么,这都是一个硬限制 通常,您应该解决服务器端的多路复用问题 现在,对于你的实际问题,你所要求的那种缓存对于承诺来说非常简单
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);
}
}
由于原始功能是一行代码,因此没有帮助程序 一个web应用程序只能有6个并发请求,因为这是硬浏览器的限制。年纪大一点的人只能做两件事。因此,无论你做什么,这都是一个硬限制 通常,您应该解决服务器端的多路复用问题 现在,对于你的实际问题,你所要求的那种缓存对于承诺来说非常简单
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是单线程的,这意味着没有并发函数调用,即使在一个时间点上所有东西都是异步的,也只运行一段代码。这意味着,将有人首先使用urly.com/foo
调用函数,缓存中没有承诺,因此它将触发GET请求并缓存并返回该承诺。当有人立即使用相同的url调用函数时,不会触发更多请求,而是会返回此url的第一个承诺,并且消费者可以订阅done/fail
回调。
当响应准备就绪且承诺得到履行,并且有人使用相同的url发出请求时,它将再次获得缓存的承诺,该承诺已经准备就绪
PromiseCaching是一种防止重复异步任务的好技术。您可以实现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是单线程的,这意味着没有并发函数调用,即使在一个时间点上所有东西都是异步的,也只运行一段代码。这意味着,将有人首先使用urly.com/foo
调用函数,缓存中没有承诺,因此它将触发GET请求并缓存并返回该承诺。当有人立即使用相同的url调用函数时,不会触发更多请求,而是会返回此url的第一个承诺,并且消费者可以订阅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);
}
您可以同时使用承诺来防止重复请求 在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);
}
一个web应用程序只能有6个并发请求,因为这是硬浏览器的限制。旧IE只能做2个。一个web应用程序只能有6个并发请求,因为这是硬浏览器的限制。老IE只能做2.谢谢你的回复,但我可能对我的要求不是很清楚。我不是在寻找一个缓存解决方案,因为我已经缓存了响应。此外,此功能将在服务器端express应用程序上。考虑到缓存是空的或过期的,同时得到多个请求时,每个请求都会发出这个HTTP数据获取请求。这就是我试图避免的。只有第一个请求应该发出服务器端http数据GET请求,任何后续请求都不应该发出,而是“等待”第一个调用响应并重新使用它。我现在明白了。很有魅力-我基本上是用节点缓存来缓存的