Javascript 确保给定参数的每个任务在Node.JS中只执行一次
我有一个Node.JS应用程序,它截图显示一个URL。因为多个用户可能同时请求同一个URL,所以我想确保在任何给定的时刻,我只抓取一次URL的屏幕截图 我通过以下方式实现了它:Javascript 确保给定参数的每个任务在Node.JS中只执行一次,javascript,node.js,concurrency,promise,Javascript,Node.js,Concurrency,Promise,我有一个Node.JS应用程序,它截图显示一个URL。因为多个用户可能同时请求同一个URL,所以我想确保在任何给定的时刻,我只抓取一次URL的屏幕截图 我通过以下方式实现了它: var inProgressUrls = {}; function grabScreenshot(url) { var inProgress = inProgressUrls[url]; if (inProgress) { return inProgress; } var promise =
var inProgressUrls = {};
function grabScreenshot(url) {
var inProgress = inProgressUrls[url];
if (inProgress) {
return inProgress;
}
var promise = new Promise(function(fulfill, reject) {
... grab screenshot ...
// Once done, remove the Promise from the map.
delete inProgressUrls[url];
});
inProgressUrls[url] = promise;
return promise;
}
我想知道的是,我是否遗漏了一些并发性问题,还是缺少了一种更好的实现方法?在我看来,您提供的代码做得很好 下面我只是尝试优化另一个角落的情况:) 一旦您调用了resolve(fully),执行就会转到事件循环,然后在下一个可用/可能的勾选中调用promise的异步操作。假设在eventloop中,有人使用相同的url调用
抓取屏幕截图
,我尝试在下面对此进行优化
delete
将在异步操作中发生,该操作只从对象中删除url
var inProgressUrls = {};
function grabScreenshot(url) {
var inProgress = inProgressUrls[url];
if (inProgress) {
return inProgress;
}
var promise = new Promise(function(fulfill, reject) {
asyncScreenGrab(url,(error, data) => {
if (!error) {
fulfill(data);
} else {
reject(error);
}
//NOT CALLING DELETE HERE TO OPTIMISE LITTLE MORE!
//IF GRAB IS CALLED WITH SAME URL WHILE AFTER THE RESOLVE OR REJECT, BUT WE ARE AT EVENT LOOP
//AND ASYN ACTIONS ARE NOT STARTED EXECUTING
});
});
inProgressUrls[url] = promise;
//DELETE THE STORED PROMISE EITHER FOR RESOLVE OR FOR REJECT
promise.then(() => delete inProgressUrls[url]).catch(() => delete inProgressUrls[url])
return promise;
}
在我看来,你提供的代码做得很好 下面我只是尝试优化另一个角落的情况:) 一旦您调用了resolve(fully),执行就会转到事件循环,然后在下一个可用/可能的勾选中调用promise的异步操作。假设在eventloop中,有人使用相同的url调用
抓取屏幕截图
,我尝试在下面对此进行优化
delete
将在异步操作中发生,该操作只从对象中删除url
var inProgressUrls = {};
function grabScreenshot(url) {
var inProgress = inProgressUrls[url];
if (inProgress) {
return inProgress;
}
var promise = new Promise(function(fulfill, reject) {
asyncScreenGrab(url,(error, data) => {
if (!error) {
fulfill(data);
} else {
reject(error);
}
//NOT CALLING DELETE HERE TO OPTIMISE LITTLE MORE!
//IF GRAB IS CALLED WITH SAME URL WHILE AFTER THE RESOLVE OR REJECT, BUT WE ARE AT EVENT LOOP
//AND ASYN ACTIONS ARE NOT STARTED EXECUTING
});
});
inProgressUrls[url] = promise;
//DELETE THE STORED PROMISE EITHER FOR RESOLVE OR FOR REJECT
promise.then(() => delete inProgressUrls[url]).catch(() => delete inProgressUrls[url])
return promise;
}