Javascript 确保给定参数的每个任务在Node.JS中只执行一次

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 =

我有一个Node.JS应用程序,它截图显示一个URL。因为多个用户可能同时请求同一个URL,所以我想确保在任何给定的时刻,我只抓取一次URL的屏幕截图

我通过以下方式实现了它:

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;
}