我想向服务器发出一系列ajax请求,然后使用我以前收到的数据进行最后的ajax请求。显然,在完成最后的请求之前,我需要等待前面的请求完成。我很难用javascript实现这一点。
我不想压垮服务器,所以理想情况下,所有请求都是按顺序完成的。
我的简单测试代码如下(用睡眠替换web请求):
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
var urls = ['1', '2', '3'];
const slowFunc = () => {
urls.forEach(async (url) => {
//Don't change this section!
console.log("a"+url);
await sleep(5000);
console.log("b"+url); //I want this to run before c
});
};
slowFunc();
console.log("c");这个打印"c“之前,睡眠是完成,这是错误的。如何使输出如下所示?
a1
b1
a2
b2
a3
b3
c出于兴趣,我怎么得到这个输出?(a和b段中的确切顺序并不重要。)
a1
a2
a3
b1
b2
b3
c我试着读ES2018:异步迭代,但这让我大吃一惊。
Update:我很快重新考虑了我的示例,所以这里有一个更好的示例(仍然不起作用):
var urls = ['https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.2.0/purify.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.8.3/system.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.18.6/slimselect.min.js'];
var results = {};
const webRequest = (url) => {
$.ajax({
type: "GET",
url: url,
}).then(data => {
results[url] = data;
console.log("b"+url+","+results[url]); //I want this to run before c
});
}
const slowFunc = () => {
urls.forEach((url) => {
console.log("a"+url);
webRequest(url);
});
};
slowFunc();
console.log("c");到目前为止,谢谢您的评论。
Update 2:基于Antonio Della Fortuna的建议解决web请求问题:
var urls = ['https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.2.0/purify.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/systemjs/6.8.3/system.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/slim-select/1.18.6/slimselect.min.js'];
var results = {};
const webRequest = (url) => {
return new Promise((resolve, reject) => {
$.ajax({
type: "GET",
url: url,
error: function (data, status, er) {
console.log("b,"+url+",failed");
resolve();
},
}).then(data => {
results[url] = data;
console.log("b,"+url+","+results[url]); //I want this to run before c
resolve();
});
});
}
const slowFunc = async () => {
for (let i = 0; i < urls.length; i++)
{
var url = urls[i];
console.log("a,"+url);
await webRequest(url);
};
};
slowFunc().then(() => {
console.log("c");
console.log(results);
})发布于 2022-01-28 22:34:14
有两种方法取决于您的用例,您可以在这里找到工作示例-> https://codesandbox.io/s/zen-carson-ksgzf?file=/src/index.js:569-624
"c": const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
var urls = ["1", "2", "3"];
const slowFunc = async () => {
await Promise.all(
urls.map(async (url) => {
//Don't change this section!
console.log("a" + url);
await sleep(5000);
console.log("b" + url); //I want this to run before c
})
);
};
slowFunc().then(() => {
console.log("c");
}); const slowFuncSeq = async () => {
for (const url of urls) {
//Don't change this section!
console.log("a" + url);
await sleep(5000);
console.log("b" + url); //I want this to run before c
}
};
slowFuncSeq().then(() => {
console.log("c");
})发布于 2022-01-28 22:16:00
在迭代过程中执行异步操作并不像您可能期望的那样工作。
当您执行forEach时,每个元素将被同步迭代。因此,每个元素将被迭代并调用回调函数,这就是为什么您首先看到每个元素的“a”日志。
这方面的例外是使用for...of循环,但对于其他迭代器,等待只会在回调函数中阻塞。
如果试图将请求的数量限制在API上,则可以实现漏桶算法。或者,您可以使用延迟函数将迭代重构为for...of循环,以阻止那些维护顺序但不太理想的请求,因为请求的速度将是延迟时间加上完成其他异步任务的时间。
https://stackoverflow.com/questions/70900765
复制相似问题