使异步调用同步

时间:2015-09-25 03:50:35

标签: javascript node.js asynchronous

我曾经用PHP构建Web应用程序,因此习惯于同步处理。

我目前正在尝试构建一个网络抓取工具。它的工作方式是

  1. 抓取代理列表
  2. 检查代理是否正常工作
  3. 使用代理抓取网页内容。
  4. 但是,我意识到大多数调用是同步的,我很难理解nodejs中的异步模块。

    这是主要方法。

    var proxyChecker = require('proxy-checker');
    var request = require('request');
    var forEach = require('async-foreach').forEach;
    var async = require('async');
    
    var proxiesJar = [];
    var goodProxies = [];
    var proxyCount = 0;    
    parseProxiesList(function(error) {
            async.each(proxiesJar, checker, function(err, result) {
                console.log('Result:' + err);
            });
        });
    

    获取代理列表

    function parseProxiesList(callback) {
        console.log("parseProxiesList");
        request('http://hidden.com', function (error, response, body) {
            if (error) {
                console.log("Error [1]");
                return callback(error);
            }
            console.log("Got proxies list");
            if (!error && response.statusCode == 200) {
                proxies = body.split(/\r?\n/);
                var shouldBreak = false;
    
                for (var i = 0; i < proxies.length; i++) {
                    if (/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:[0-9]{1,5}/.test(proxies[i])) {
                        p = proxies[i].split(' ');
                        var elts = p[0].split(':');
                        var host = elts[0];
                        var port = elts[1];
                        proxiesJar.push(host + ":" + port);
                    }
                }
                callback(null, 1);
            }
        });
    }
    

    获取代理列表后,它会检查代理是否正常工作。

    var checker = function(proxy, callback) {
        var p = proxy.split(':');
        var host = p[0];
        var port = p[1];
        console.log('[Checking] ' + host + ':' + port);
        proxyChecker.checkProxy(host, port, {url: 'http://google.com',regex: /Google/}, function(host, port, ok, statusCode, err) {
    
            if(!ok) {
                console.log("Proxy don't work: " + host + ":" + port);
                return callback(err);
            } else {
                console.log("Working proxy: " + host + ":" + port);
                goodProxies.push(host + ":" + port);
                return callback(null, host + ":" + port);
            }
        });
    };
    

    然而,日志结果是

    [Checking] 1.1.1.1:80
    [Checking] 2.2.2.2:80
    .
    .
    .
    Working proxy: 1.1.1.1:80
    Working proxy: 2.2.2.2:80
    

    而不是

    [Checking] 1.1.1.1:80
    Working proxy: 1.1.1.1:80
    
    [Checking] 2.2.2.2:80
    Working proxy: 2.2.2.2:80
    

2 个答案:

答案 0 :(得分:1)

async.each并行执行每个项目的迭代器。

使用async.eachSeries进行同步通话。

答案 1 :(得分:0)

你可以试试promises,创建一个获得代理的承诺,然后执行一个承诺来检查它。

您可以在here

上找到有关承诺的更多信息

示例:

function parseProxiesList() {
    var deferred = Q.defer()
    console.log("parseProxiesList");
    request('http://hidden.com', function (error, response, body) {
        if (error) {
            console.log("Error [1]");
            deferred.reject(error);
        }
        console.log("Got proxies list");
        if (!error && response.statusCode == 200) {
            proxies = body.split(/\r?\n/);
            var shouldBreak = false;

            for (var i = 0; i < proxies.length; i++) {
                if (/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:[0-9]{1,5}/.test(proxies[i])) {
                    p = proxies[i].split(' ');
                    var elts = p[0].split(':');
                    var host = elts[0];
                    var port = elts[1];
                    proxiesJar.push(host + ":" + port);
                }
            }
            deffered.resolve(proxiesJar);
        }
        return deffered.promise;
    });
}

这样您就创建了获取代理列表的承诺。同样,你可以用来检查代理。