【问题标题】:Running function in a loop concurrently同时在循环中运行函数
【发布时间】:2020-08-08 17:18:57
【问题描述】:

我有这个非常容易理解的 javascript 循环。它本质上是循环调用infoGetter()。但是,问题是它一次调用infoGetter() 20 次。我只希望3 infoGetters() 始终在任何一个时间点工作(除非我们达到了 while 循环条件)。

var min = 1;
var limit = 1000;
var myId = 12345;
while (min < limit) {
    var max = min + 50;
    infoGetter(myId, min, max);
    min = max;
}


function infoGetter(myId, min, max) {

    return $.ajax({
        type: "POST",
        url: "get-info.php",
        dataType: "json",
        data: {
            myId: myId,
            min: min,
            max: max
        },
        success: function(data) {
            /* to stuff here (not important to this question) */
        }
    });

}

我希望脚本如何工作:

  1. 在循环中调用infoGetter(myId, 1, 51);并在后台等待返回值
  2. 增加最小值,它调用infoGetter(myID, 51, 102);并在后台等待返回值
  3. 增加最小值,调用infoGetter(myID, 102, 153);并在后台等待返回值

现在,一旦infoGetter() 之一获得返回值,它就会使用新参数再次调用它(因为总是需要同时运行3 infoGetter(),除非它到达while循环条件)。新参数显然是我们更新的新 myIdminmax 值,因为我们正在循环中更改 minmax

3 可以是不同的数字,例如 5。所以我们可以同时运行 5 个infoGetter()

【问题讨论】:

    标签: javascript jquery ajax while-loop concurrency


    【解决方案1】:

    您可以创建一个调用infoGetter 的函数,如果有更多请求需要通过链接到infoGetter 返回的ajax 调用进行,则递归调用自身。然后调用该函数3次,这样每当请求成功时,它就会再次调用makeRequest

    let min = 1;
    const limit = 1000;
    const myId = 12345;
    const makeRequest = () => {
      const max = min + 50;
      infoGetter(myId, min, max)
        .then(() => {
          if (min < limit) {
            makeRequest();
          }
        });
      min = max;
    };
    
    makeRequest();
    makeRequest();
    makeRequest();
    

    const maximumConcurrentRequests = 3;
    for (let i = 0; i < maximumConcurrentRequests; i++) {
      makeRequest();
    }
    

    如果你希望进程在请求失败的情况下继续进行,catch Promise 在调用 .then 之前:

    infoGetter(myId, min, max)
      .catch(() => void 0)
      .then(() => {
    

    或者,完整的:

    let min = 1;
    const limit = 1000;
    const myId = 12345;
    const makeRequest = () => {
      const max = min + 50;
      infoGetter(myId, min, max)
        .catch(() => void 0)
        .then(() => {
          if (min < limit) {
            makeRequest();
          }
        });
      min = max;
    };
    

    现场演示,其中infoGetter 使用 Promise 模拟,该 Promise 在 0 到 5 秒之间的随机数后解析:

    const infoGetter = () => new Promise(res => setTimeout(res, Math.random() * 5000));
    
    let min = 1;
    const limit = 1000;
    const myId = 12345;
    const makeRequest = () => {
      console.log('making request for', min);
      const max = min + 50;
      infoGetter(myId, min, max)
        .catch(() => void 0)
        .then(() => {
          if (min < limit) {
            makeRequest();
          }
        });
      min = max;
    };
    
    const maximumConcurrentRequests = 3;
    for (let i = 0; i < maximumConcurrentRequests; i++) {
      makeRequest();
    }

    如果您还想检测所有请求何时完成,请将初始 Promise 放入数组中,从递归调用中返回 Promises,然后在数组上调用 Promise.all

    const infoGetter = () => new Promise(res => setTimeout(res, Math.random() * 5000));
    
    let min = 1;
    const limit = 500;
    const myId = 12345;
    const makeRequest = () => {
      console.log('making request for', min);
      const thisMin = min;
      const max = min + 50;
      min = max;
      return infoGetter(myId, thisMin, max)
        .catch(() => void 0)
        .then(() => {
          if (min < limit) {
            return makeRequest();
          }
        });
    };
    
    const maximumConcurrentRequests = 3;
    Promise.all(
      Array.from(
        { length: maximumConcurrentRequests },
        makeRequest
      )
    )
      .then(() => {
        console.log('All done');
      });

    【讨论】:

    • 你能告诉我你是如何完全使用第二种方法的吗?
    • 完全一样,只是中间加了.catch(() =&gt; void 0)这一行。
    • 那么当您调用makeRequest() 时,是否存在minmax 重复的实例?还是一切都会顺利进行?
    • 否,min 在每次调用时同步递增,因此每个请求都会不同
    • 哦,我明白了,我在代码中的哪一点知道不需要再执行infoGetters()(因此,我们已经调用了所有可能的infoGetters()。因为我想基本上更新一个名为 progress 的 html id 并将该 htl 值设置为 All info has been grabbed
    猜你喜欢
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 2011-01-31
    • 2021-08-31
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多