两个异步模块功能异步工作

时间:2016-01-10 13:52:54

标签: javascript node.js asynchronous

我试图废弃数千页。所以我使用了async.timesSeries和async.waterfall。每个功能都可以很好地同步工作,但它们不能一起工作。我该怎么办?

逻辑很简单。

  1. 因为我想要抓取页面是“http://udb.kr/local/category/390101?page=”1~1167,async.timesSeries循环1到1167

  2. async.waterfall废弃网页的组件

  3. 但是控制台向我显示的消息看起来像这样

    info.NM values // just for explain, It shows me each attires of obj because I insert console.log(info.NM) for verifying.
    info.NM values
    info.NM values
    info.NM values and randomly ----- page number -----
    ...
    ['done',
    'done',
    'done',
    'done',
    'done',
    ...
    'done']
    info.NM values again
    
    .../Users/Snark/Dev/job_apply/cheerio_job_app_list.js:29
                if (tObj[m+1].children != 0) {info.nAddr = tObj[m+1].firstChild.data}else{info.nAddr = null};
                             ^
    
    TypeError: Cannot read property 'children' of undefined
        at /Users/Snark/Dev/job_apply/cheerio_job_app_list.js:29:17
        at fn (/Users/Snark/node_modules/async/lib/async.js:746:34)
        at /Users/Snark/node_modules/async/lib/async.js:1212:16
        at /Users/Snark/node_modules/async/lib/async.js:166:37
        at /Users/Snark/node_modules/async/lib/async.js:706:43
        at /Users/Snark/node_modules/async/lib/async.js:167:37
        at /Users/Snark/node_modules/async/lib/async.js:1208:30
        at Request._callback (/Users/Snark/Dev/job_apply/cheerio_job_app_list.js:21:6)
        at Request.self.callback (/Users/Snark/node_modules/request/request.js:198:22)
        at emitTwo (events.js:87:13)
    

    这是js代码。

    var request = require("request"),
        cheerio = require("cheerio"),
        jsonfile = require("jsonfile"),
        fs = require("fs"),
        async = require("async");
    
    var info = {},
        dbArray = [];
    
    var url = "http://udb.kr/local/category/390101?page=";
    
    async.timesSeries(1166, function(n, next) {
        var page = n + 1
        async.waterfall([
            function(callback) {
                request(url + page, function(error, response, html) {
                    if (error) {
                        throw error
                    };
                    var $ = cheerio.load(html),
                        tObj = $('tbody tr td');
                    callback(null, tObj);
                });
            },
            function(tObj, callback) {
    
                for (var m = 0; m < 150; m = m + 5) {
                    if (tObj[m]) {
                        info.NM = tObj[m].firstChild.children[0].data
                    } else {
                        info.NM = null
                    };
                    if (tObj[m + 1].children != 0) {
                        info.nAddr = tObj[m + 1].firstChild.data
                    } else {
                        info.nAddr = null
                    };
                    console.log(info.NM);
                    dbArray.push(info);
                }
                callback(dbArray, callback);
            },
            function(dbArray, callback) {
                fs.appendFile('./jobDB_l.json', JSON.stringify(dbArray), function (err) {
                    if (err)
                        throw err;
                });
                callback(null, 'done');
            }
        ], function(err, result) {
            console.log('----- ' +page+ '-----');
        });
        next(null, 'done');
    }, function(err, result) {
        console.log(result)
    });
    

2 个答案:

答案 0 :(得分:0)

if (tObj[m+1] && tObj[m+1].children != 0)

答案 1 :(得分:0)

要使这些在每个timesSeries迭代中使用瀑布的方式协同工作,您需要从瀑布调用的完成回调中调用timesSeries done回调。现在,你在很久之前调用它,这意味着timesSeries不会等待瀑布完成。

你可以通过改变这个来做到这一点:

], function(err, result) {
    console.log('----- ' +page+ '-----');
});
next(null, 'done');

到此:

], function(err, result) {
    console.log('----- ' +page+ '-----');
    next(null, 'done');
});

您使用for的硬编码m < 150循环限制而不是使用内容的实际长度,这似乎很奇怪。您可以轻松地运行内容的末尾并可能导致问题。

而且,您的错误处理可能也无法正常工作。如果你在异步throw回调中request(),那就不会去任何地方了。您需要更好的错误处理,例如调用callback(error)将错误传递给async.waterfall()

你也可能希望在try / catch中包围所有DOM,所以如果你在那里抛出任何异常,你可以自己捕获它们,分析它们然后修复代码。