【问题标题】:node.js promise.then() get excuted without all() fulfillmentnode.js promise.then() 在没有 all() 实现的情况下被执行
【发布时间】:2017-10-23 11:18:45
【问题描述】:

我在 node.js 中编写 crawler 时遇到了问题。问题是 promise 的 then() 一旦被调用就会被执行,但当 promise 数组 all() 返回执行时不会执行。

我一直在寻找并试图找到原因,但似乎以前没有人遇到过这个问题。

var http = require('https');
var cheerio = require('cheerio');
var Promise = require('bluebird');
var url = 'https://developer.teamwork.com/';


function filterData(html) {
    var $ = cheerio.load(html);
    // console.log(html);
    // var data = {
    //     title: title,
    //     APIs: [{
    //         apiTitle: apiTitle,
    //         type: type,
    //         apiUrl: apiUrl,
    //         description: description,
    //         req: {
    //             description: description,
    //             content: {}
    //         },
    //         res: {
    //             description: description,
    //             content: {}
    //         }
    //     }]
    // };
    var title = $('.api--main').find('h2').text();
    console.log('|' + title + '|');

}


function filterModules(html) {
    var $ = cheerio.load(html);
    var modules = $('.api--main').find('.lev1');
    // [{
    //     moduleTitle: '',
    //     moduleURL: ''
    // }]
    var modulesData = [];
    var module = '', moduleTitle = '', Url = '';
    modules.each(function (item) {
        module = $(this).find('a');
        moduleTitle = module.text();
        Url = module.attr('href');
        if (!Url.match('//')){
            moduleUrl = url + Url;
        } else {
            moduleUrl = Url;
        }
        modulesData.push({
            moduleTitle: moduleTitle,
            moduleUrl: moduleUrl
        });
    });

    return modulesData;
}

function printModuleInfo(data) {
    var moduleTitle;
    var moduleUrl;
    var printResults = '';
    data.forEach(function (item) {
        moduleTitle = item.moduleTitle;
        moduleUrl = item.moduleUrl;
        printResults = printResults + '<' + moduleTitle + '>\n' + '  URL: ' + moduleUrl + '\n';
    });
    return printResults;
}

function getContents(url,title) {
    return new Promise(function(resolve, reject) {
        http.get(url, function(res) {
            console.log('crawling:'+url);
            var html = '';

            res.on('data', function(data) {
                html += data;
            });

            res.on('end', function() {
                resolve({
                    title: title,
                    html: html
                });
            });
        }).on('error', function(e) {
            reject(e);
        });

    });
}



var allOriContents = [];

http.get(url, function (res) {
    var html = '';
    res.on('data', function (data) {
        html += data;
    });

    res.on('end', function () {
        // console.log(html);
       var modulesData = filterModules(html);
        modulesData.forEach(function (item) {
            // console.log(item.moduleTitle);
            if (!(item.moduleTitle === 'Introduction')) {
                allOriContents.push(getContents(item.moduleUrl,item.moduleTitle));
                // console.log(allOriContents[0]);
            } else {}
        });
    });
}).on('error', function () {
    console.log('There are errors when getting urls.');
});
// setTimeout(function () {
    Promise
        .all(allOriContents)
        .then(function (obj) {
            console.log(obj.length);
            var modulesData = [];
            var module;
            var moduleData;
            obj.forEach(function (item) {
                console.log(item.title);
                module = filterData(item.html);
                moduleData = {
                    title: item.title,
                    data: module
                };
                modulesData.push(module);
            });
            modulesData.sort(function(a, b) {
                return a.title < b.title;
            });
        })
        .catch(function (err) {
            console.log(err);
        });
// }, 120000);

任何帮助将不胜感激。谢谢。

【问题讨论】:

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


    【解决方案1】:

    那是因为您的 http.get 也是一个异步调用,并且在执行 Promise.all(allOriContents) 时, allOriContents 很可能是空的。

    将你的承诺代码移到 res.end 中

    res.on('end', function () {
            // console.log(html);
           var modulesData = filterModules(html);
            modulesData.forEach(function (item) {
                // console.log(item.moduleTitle);
                if (!(item.moduleTitle === 'Introduction')) {
                    allOriContents.push(getContents(item.moduleUrl,item.moduleTitle));
                    // console.log(allOriContents[0]);
                } else {}
            });
            Promise
        .all(allOriContents)
        .then(function (obj) {
            console.log(obj.length);
            var modulesData = [];
            var module;
            var moduleData;
            obj.forEach(function (item) {
                console.log(item.title);
                module = filterData(item.html);
                moduleData = {
                    title: item.title,
                    data: module
                };
                modulesData.push(module);
            });
            modulesData.sort(function(a, b) {
                return a.title < b.title;
            });
        })
        .catch(function (err) {
            console.log(err);
        });
        });
    

    【讨论】:

    • 或者你也可以将你的 http.get 包装在一个 Promise 中,并在该 Promise 解决后执行你的 Promise.all 代码。
    • 不知道http.get也是异步的,我试试看,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 2021-10-22
    • 2012-02-02
    相关资源
    最近更新 更多