提问人:Zoey Malkov 提问时间:4/25/2020 更新时间:4/25/2020 访问量:239
在循环中并发运行函数
Running function in a loop concurrently
问:
我有这个 javascript 循环,它很容易理解。它本质上是一个循环调用。但是,问题是它一次调用 20 次。我只希望始终在任何一个时间点工作(除非我们达到 while 循环条件)。infoGetter()
infoGetter()
3
infoGetters()
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) */
}
});
}
我希望脚本如何工作:
- 在循环中,它会在后台调用并等待返回值
infoGetter(myId, 1, 51);
- 增加 min,它在后台调用并等待返回值
infoGetter(myID, 51, 102);
- 增加 min,它在后台调用并等待返回值
infoGetter(myID, 102, 153);
现在,一旦其中一个获得返回值,它就会使用新参数再次调用它(因为除非它达到 while 循环条件,否则总是需要一次运行 ')。新参数显然是我们更新的新 , , 值,因为我们正在更改和循环中。infoGetter()
3
infoGetter()
myId
min
max
min
max
其中 可以是不同的数字,例如 。因此,我们可以同时运行 5 个。3
5
infoGetter()
答:
0赞
CertainPerformance
4/25/2020
#1
您可以创建一个函数来调用 ,如果需要通过链接到 返回的 ajax 调用来发出更多请求,则可以递归调用自身。然后调用该函数 3 次,以便每当请求成功时,它都会再次调用:infoGetter
infoGetter
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();
}
如果希望该过程在请求失败后继续,则在调用它之前,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()
min
max
0赞
CertainPerformance
4/25/2020
否,在每次调用时都会同步递增,因此每个请求都会有所不同min
0赞
Zoey Malkov
4/25/2020
哦,我明白了,在代码的什么时候我知道不再需要进行(因此,我们已经完成了调用所有可能的.因为我想基本上更新一个 html id 调用并将该 htl 值设置为infoGetters()
infoGetters()
progress
All info has been grabbed
评论