如何管理多个承诺

How to manage multiple promises

本文关键字:承诺 管理 何管理      更新时间:2023-09-26

我正在使用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)后,我进行了处理以获取所有项目的URL

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,确保它们完全按正确顺序提取,该怎么办?

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

然后将解析添加到CCD_ 18方法中。

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