javascript - 如何管理多个 Promise

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

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

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

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

它确实会爬行。它确实获得了我需要的所有元素,而且不缺少任何信息。

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

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

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

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

最佳答案

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

我想为了保持结果的顺序,您可能需要使用 Promise.all 。当所有项目都被完全抓取时,它还有助于获取全部完成消息。

我将从更改 fetchPage 函数开始,通过使用 mapurl 转换为 fetchItem promise 数组,我可以传递给 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)
            );
    });
}

关于javascript - 如何管理多个 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36631083/

相关文章:

javascript - 如果在 angularJS 的配置中配置,则测试 stateProvider 状态在 $state 上返回 null

javascript - 封装与 div 共享同一类的同级元素 [一次两个]

css - 在表单提交上显示元素

javascript - 异步获取多个json文件后触发回调

javascript - React 中如何判断哪个组件触发了事件处理器?

javascript - 获取数据表中页面的值?

node.js - 从 Nodejs6.1 到 Nodejs8.1 运行时更新后 GetObject() 不起作用

java - 如何将以下 JAVA 加密复制为等效的 NODEJS(使用 node-rsa 或 crypto 模块)?

java - 循环中的 CompletableFuture : How to collect all responses and handle errors

android import android-async-http-master 有错误