如何管理多个承诺

时间:2016-04-14 18:24:51

标签: javascript node.js asynchronous promise web-crawler

我正在使用node.js编写一个爬虫。首先,我需要获取主页面以获取该页面上每个项目的URL,然后我抓取每个项目的URL以逐个获取它们的详细信息

fetchPage(url)是获取链接的HTML文本

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

我在获取主页后通过getUrls进行处理以获取所有项目的网址

fetchItem(url)是另一个Promise,可确保项目的每个HTML文字在被getItem提取后通过fetchPage进行处理

function fetchItem(url){
    return new Promise(
        (resolve,reject)=>{
            fetchPage(url).then(
                (result)=>{
                    getItem(result);
                },
                (error)=>reject(error)
            );
        });
}

它会抓取。它确实得到了我需要的所有物品,而且没有任何信息。

但我的代码有问题。为什么控制台没有为我记录Done消息?

结果的顺序不正确。已爬网结果的顺序与我预期的不同,它与网站上的订单不同。

请指出我对这些异步控制有什么误解和做错了?如何确保它们的顺序?如何修复此代码以满足?

如果我想在完全抓取所有项目之后记录消息All done,我该怎么办?确保它们按照正确的顺序完全取出?

1 个答案:

答案 0 :(得分:2)

Done未被调用,因为您未解析Promise函数中创建的fetchItem

我想维持结果的顺序,您可能想要使用Promise.all。它还有助于在完全抓取所有项目时收到All done消息。

我将首先使用fetchPageurls转换为fetchItem承诺数组来更改map功能,我可以传递给Promise.allfetchPage(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) ); 像这样的东西

fetchItem

然后将解决方案添加到您的function fetchItem(url){ return new Promise( (resolve,reject)=>{ fetchPage(url).then( (result)=>{ resolve(getItem(result)); }, (error)=>reject(error) ); }); } 方法。

var USState = ["Alabama", "Alaska" , "Arizona" ,"Arkansas", "California", 
        "Colorado", "Connecticut"];

$(document).ready(function() 
{ 
stateselect = document.getElementById("state");
for(i=0; i < USState.length; ++i) 
{
    var el=document.createElement('option');
    el.textContent = USState[i];
    stateselect.appendChild(el);
}