如何管理多个承诺
How to manage multiple promises
我正在使用 node.js 编写爬虫程序。首先,我需要获取主页以获取该页面上每个项目的URL,然后我爬取每个项目的URL以逐一获取它们的详细信息
fetchPage(url)
是得到HTML一个link
的文本
function fetchPage(url){
return new Promise(
(resolve,reject)=>{
agent
.get(url)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
});
}
这是本爬虫的全局调用
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
for (var i=0;i<5;i++){
fetchItem(urls[i].link).then(
(result)=>{
console.log('Done');
},
(error)=>console.log(error)
);
}
},
(error)=>console.log(error)
);
我在获取主页后处理了所有项目的 URLs(通过 getUrls
)
fetchItem(url)
是另一个 Promise
,它确保项目的每个 HTML 文本在被 fetchPage
[=21 获取后应通过 getItem
处理=]
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
getItem(result);
},
(error)=>reject(error)
);
});
}
它确实会爬行。它确实得到了我需要的所有物品,而且没有任何信息缺失。
但是我的代码有问题。为什么控制台不为我记录 Done
消息?
结果顺序不正确。爬取结果的顺序和我预想的不一样,和网站上的顺序不一样
请指出我对这些异步控制的误解和错误之处?如何保证它们的顺序?如何修复此代码以满足?
如果我想在完全抓取所有项目后记录一条消息 All done
,我应该怎么做,以确保它们以正确的顺序完全提取?
Done
未被调用,因为您没有解析在 fetchItem
函数中创建的 Promise
。
我想为了保持结果的顺序,您可能需要使用 Promise.all。当所有项目都被完全抓取时,它也有助于获得 All done
消息。
我将从更改 fetchPage
函数开始,方法是将 urls
转换为使用 map
的 fetchItem
承诺数组,我可以将其传递给 Promise.all
。像这样
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
var promises = urls.map((url) => fetchItem(url.link));
Promise.all(promises).then((values) => {
console.log('All done');
console.log(values);
}, (error) => {
console.log(error);
});
},
(error)=>console.log(error)
);
然后将 resolve 添加到您的 fetchItem
方法。
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
resolve(getItem(result));
},
(error)=>reject(error)
);
});
}
我正在使用 node.js 编写爬虫程序。首先,我需要获取主页以获取该页面上每个项目的URL,然后我爬取每个项目的URL以逐一获取它们的详细信息
fetchPage(url)
是得到HTML一个link
function fetchPage(url){
return new Promise(
(resolve,reject)=>{
agent
.get(url)
.end(function(err,res){
if (err){
reject(err);
} else{
resolve(res.text);
}
});
});
}
这是本爬虫的全局调用
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
for (var i=0;i<5;i++){
fetchItem(urls[i].link).then(
(result)=>{
console.log('Done');
},
(error)=>console.log(error)
);
}
},
(error)=>console.log(error)
);
我在获取主页后处理了所有项目的 URLs(通过 getUrls
)
fetchItem(url)
是另一个 Promise
,它确保项目的每个 HTML 文本在被 fetchPage
[=21 获取后应通过 getItem
处理=]
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
getItem(result);
},
(error)=>reject(error)
);
});
}
它确实会爬行。它确实得到了我需要的所有物品,而且没有任何信息缺失。
但是我的代码有问题。为什么控制台不为我记录 Done
消息?
结果顺序不正确。爬取结果的顺序和我预想的不一样,和网站上的顺序不一样
请指出我对这些异步控制的误解和错误之处?如何保证它们的顺序?如何修复此代码以满足?
如果我想在完全抓取所有项目后记录一条消息 All done
,我应该怎么做,以确保它们以正确的顺序完全提取?
Done
未被调用,因为您没有解析在 fetchItem
函数中创建的 Promise
。
我想为了保持结果的顺序,您可能需要使用 Promise.all。当所有项目都被完全抓取时,它也有助于获得 All done
消息。
我将从更改 fetchPage
函数开始,方法是将 urls
转换为使用 map
的 fetchItem
承诺数组,我可以将其传递给 Promise.all
。像这样
fetchPage(link).then(
(result)=>{
const urls=getUrls(result);
var promises = urls.map((url) => fetchItem(url.link));
Promise.all(promises).then((values) => {
console.log('All done');
console.log(values);
}, (error) => {
console.log(error);
});
},
(error)=>console.log(error)
);
然后将 resolve 添加到您的 fetchItem
方法。
function fetchItem(url){
return new Promise(
(resolve,reject)=>{
fetchPage(url).then(
(result)=>{
resolve(getItem(result));
},
(error)=>reject(error)
);
});
}