在循环中并发运行函数

Running function in a loop concurrently

提问人:Zoey Malkov 提问时间:4/25/2020 更新时间:4/25/2020 访问量:239

问:

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

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. 增加 min,它在后台调用并等待返回值infoGetter(myID, 51, 102);
  3. 增加 min,它在后台调用并等待返回值infoGetter(myID, 102, 153);

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

其中 可以是不同的数字,例如 。因此,我们可以同时运行 5 个。35infoGetter()

JavaScript jQuery ajax while 循环 并发

评论


答:

0赞 CertainPerformance 4/25/2020 #1

您可以创建一个函数来调用 ,如果需要通过链接到 返回的 ajax 调用来发出更多请求,则可以递归调用自身。然后调用该函数 3 次,以便每当请求成功时,它都会再次调用:infoGetterinfoGettermakeRequest

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

如果希望该过程在请求失败后继续,则在调用它之前,Promise 会:catch.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;
};

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

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

评论

0赞 Zoey Malkov 4/25/2020
你能告诉我你是如何完全做到第二种方法的吗?
0赞 CertainPerformance 4/25/2020
除了在中间添加了那行之外,它完全相同。.catch(() => void 0)
0赞 Zoey Malkov 4/25/2020
那么当你调用时,是否有任何实例,是重复的?还是一切仍会按部就班地进行?makeRequest()minmax
0赞 CertainPerformance 4/25/2020
否,在每次调用时都会同步递增,因此每个请求都会有所不同min
0赞 Zoey Malkov 4/25/2020
哦,我明白了,在代码的什么时候我知道不再需要进行(因此,我们已经完成了调用所有可能的.因为我想基本上更新一个 html id 调用并将该 htl 值设置为infoGetters()infoGetters()progressAll info has been grabbed