【问题标题】:How to manage multiple promises如何管理多个 Promise
【发布时间】:2016-04-14 18:24:51
【问题描述】:

我正在使用 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)
);

我在获取主页后处理获取所有项目的 URL(通过getUrls

fetchItem(url) 是另一个Promise,它确保项目的每个HTML 文本在被fetchPage 获取后都应通过getItem 处理

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

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

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

结果的顺序不正确。爬取结果的顺序和我想象的不一样,和网站上的顺序不一样。

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

如果我想在所有项目被完全抓取后记录一条消息All done,并确保它们以正确的顺序完全提取,我该怎么办?

【问题讨论】:

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


    【解决方案1】:

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

    我想为了保持结果的顺序,你可能想使用Promise.all。当所有项目都被完全爬取时,它还有助于获取All done 消息。

    我将从更改 fetchPage 函数开始,通过使用 mapurls 转换为 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)
    );
    

    然后将解析添加到您的 fetchItem 方法中。

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

    【讨论】:

    • 你能用我的代码更具体地演示一下吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    相关资源
    最近更新 更多