Javascript 同步处理嵌套数组
我正在重构一些爬网网页的代码(删除“回调地狱”),并希望在每个请求之间有三秒钟的延迟。以下是请求函数:Javascript 同步处理嵌套数组,javascript,asynchronous,async-await,Javascript,Asynchronous,Async Await,我正在重构一些爬网网页的代码(删除“回调地狱”),并希望在每个请求之间有三秒钟的延迟。以下是请求函数: const getHTML = function(page, i) { return new Promise(function(resolve, reject) { setTimeout(function () { api.makeAPIGetRequest(page).then((html) => { re
const getHTML = function(page, i) {
return new Promise(function(resolve, reject) {
setTimeout(function () {
api.makeAPIGetRequest(page).then((html) => {
resolve(html);
}).catch((err) => {
reject(err);
})
}, i * 3000);
});
}
我正在遍历一个对象数组,然后遍历一个数组:
let p = [
{
location: 'England',
pages: [1, 3, 5]
},
{
location: 'Scotland',
pages: [2, 4, 6]
}
];
问题是输出是随机的(因为延迟):
应该是:
Page 1 - Loaded
Page 3 - Loaded
Page 5 - Loaded
Page 2 - Loaded
Page 4 - Loaded
Page 6 - Loaded
这是我的密码:
p.map(async (data) => {
await crawlLocationPages(data);
})
function crawlLocationPages(data) {
return Promise.all(
data.pages.map(async (page, i) => {
await getHTML(page, i).then((html) => { // <-- waits 3 seconds
console.log('Page ' + page + ' - Loaded' );
});
})
).then(() => {
})
};
p.map(异步(数据)=>{
等待爬网定位页面(数据);
})
函数爬行位置页面(数据){
回报你的承诺(
data.pages.map(异步(第页,i)=>{
等待getHTML(第i页),然后((html)=>{//{
})
};
我宁愿保持对象和数组模型不变
非常感谢您的帮助。这种方法可能不太容易混淆,但只有在每个请求所需时间不超过3秒时才有效
pages=p.flatMap(位置=>location.pages);
page=0;
var interval=setInterval(()=>{
如果(页面===页面长度){
间隔时间;
}
makeAPIGetRequest(页面[page++])。然后((html)=>{
log('Page'+Page+'-Loaded');
}).catch((错误)=>{
控制台错误(err);
});
},3000);
这种方法可能不太容易混淆,但只有在每个请求所需时间不超过3秒时才有效
pages=p.flatMap(位置=>location.pages);
page=0;
var interval=setInterval(()=>{
如果(页面===页面长度){
间隔时间;
}
makeAPIGetRequest(页面[page++])。然后((html)=>{
log('Page'+Page+'-Loaded');
}).catch((错误)=>{
控制台错误(err);
});
},3000);
使用ES6生成器和产量解决了这个问题
function* crawlGenerator() {
for (let i = 0; i <= (p.length - 1); i++) {
yield crawlLocationPages(p[i]);
}
}
let crawl = crawlGenerator();
crawl.next();
function crawlLocationPages(data) {
return Promise.all(
data.pages.map(async (page, i) => {
await getHTML(page, i).then((html) => { // <-- waits 3 seconds
console.log('Page ' + page + ' - Loaded' );
});
})
).then(() => {
crawl.next();
})
};
函数*crawlGenerator(){
for(设i=0;i{
等待getHTML(第i页),然后((html)=>{//{
crawl.next();
})
};
此处的更多信息:使用ES6生成器和产量解决了此问题
function* crawlGenerator() {
for (let i = 0; i <= (p.length - 1); i++) {
yield crawlLocationPages(p[i]);
}
}
let crawl = crawlGenerator();
crawl.next();
function crawlLocationPages(data) {
return Promise.all(
data.pages.map(async (page, i) => {
await getHTML(page, i).then((html) => { // <-- waits 3 seconds
console.log('Page ' + page + ' - Loaded' );
});
})
).then(() => {
crawl.next();
})
};
函数*crawlGenerator(){
for(设i=0;i{
等待getHTML(第i页),然后((html)=>{//{
crawl.next();
})
};
这里有更多信息:await
在.map
和.forEach
中不起作用,但它在中对循环起作用。当然,它必须在异步
函数中
const run = async () => {
for(let data of p){
await crawlLocationPages(data);
}
}
const crawlLocationPages = async data => {
for(let page of data.pages){
const html = await getHTML(page);
console.log('Page ' + page + ' - Loaded - HTML = ', html );
await pause();
}
}
const pause = () => new Promise( (resolve, reject) => setTimeout(resolve, 3000) );
run()
await
在.map
和.forEach
内部不起作用,但它在内部对循环起作用。当然,它必须在异步
函数内部
const run = async () => {
for(let data of p){
await crawlLocationPages(data);
}
}
const crawlLocationPages = async data => {
for(let page of data.pages){
const html = await getHTML(page);
console.log('Page ' + page + ' - Loaded - HTML = ', html );
await pause();
}
}
const pause = () => new Promise( (resolve, reject) => setTimeout(resolve, 3000) );
run()
您好,您的问题中没有包含_delay的值,我假设它是1000
ms,对吗?3000ms-我希望每个页面请求之间有3秒的延迟。您可以将所有API响应存储在一个数组中,并仅在所有请求完成后打印。或者,您可以在响应到来时打印,只需维护一个包含所有响应的数组onses已打印,打印前请检查。如果之前的响应尚未打印,请将响应放入对象中,稍后再打印。您好,您的问题中没有包含_delay的值,我假设它是1000
ms,对吗?3000ms?我希望每个页面请求之间有3秒的延迟。您可以存储所有API请求在数组中进行PONSE,并在所有请求完成后才打印。或者,您可以在响应出现时打印,只需维护一个包含所有已打印响应的数组,并在打印前检查检查。如果之前的响应尚未打印,请将响应放入对象中,稍后再打印。这是一个不错的解决方案。我使用ES6生成器是因为他getHTML
函数目前不在我的范围内。解决方案不错。我使用ES6生成器,因为getHTML
函数目前不在我的范围内。