0

我是一个 nodejs 新手,已经习惯了所有异步的东西。

使用: - Node-MySQL (https://github.com/felixge/node-mysql) - 现在请求 (https://github.com/mikeal/request) 模块。

我正在查询一大串 URL(10,000 个 URL)并尝试向它们发送 HTTP GET 请求以获取它们的 HTTP 状态。

它可以工作,但问题是,当我运行代码时,返回 MySQL 查询的每一行时,都会调用 processURL 函数,它会在每个 URL 值之后记录“BEFORE”和“AFTER”,(就我可以理解)发送 HTTP 请求,但在返回 HTTP 状态之前等待 MySQL 查询完成。

简单地说,它无法在查询运行时检查这些 URL 并返回它们的结果。它等待查询完成以返回 HTTP 请求的结果。

这对我来说看起来毫无意义,因为它在流式传输每一行时运行 processURL 函数。这是完整的代码:

var mysql       = require('mysql');

var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : '',
  database : 'urlDB',
});

var query = connection.query('SELECT * FROM urls LIMIT 10000');
query.on('error', function(err) {
    console.log(err);
})
query.on('result', function(row) {
    processURL(row.urlValue, function() {

    });
    console.log(row.urlValue);
})

function processURL (url){
    var request     = require('request');
    var startTime = new Date();
    console.log('BEFORE');
    request({
        uri: url,
        method: 'GET',
    }, function(error, response, body) {
        console.log('INSIDE');
        var endTime = new Date();

        if (!error) {
            console.log(response.statusCode + '  Start: ' + startTime + '  End: ' + endTime);
        } else {
            console.log('timeout');
        }
    })
    console.log('AFTER');
}

输出如下: www.google.com BEFORE AFTER www.yahoo.com BEFORE AFTER www.cnn.com BEFORE AFTER ...但在查询完成之前没有'INSIDE'。

任何帮助表示赞赏,非常感谢。

4

1 回答 1

0

我修改了您的示例以更慢地获得结果,并且它按预期工作。你可以复制粘贴试试:

var request = require('request');

var urls = ['http://google.com', 'http://yahoo.com', 'http://ninjaturtles.com'];

getResultSlowly();

function getResultSlowly() {
  var result = urls.shift();
  if (!result) return;

  console.log(result);
  processUrl(result);
  setTimeout(getResultSlowly, 1000);
}

function processUrl(url) {
  var startTime = new Date();
  console.log('BEFORE');
  request({
    uri: url,
    method: 'GET',
  }, function(error, response, body) {
    console.log('INSIDE');
    var endTime = new Date();

    if (!error) {
      console.log(response.statusCode + '  Start: ' + startTime + '  End: ' + endTime);
    } else {
      console.log('timeout');
    }
  })
  console.log('AFTER');
}

网络延迟很可能只是掩盖了异步行为。

您的查询结果将几乎立即返回,result并在您执行代码后立即触发几个事件。但是,您的request活动将花费相当长的时间(即使只是一两毫秒),因为它必须与 google 或 yahoo 或其他任何人建立联系。

输出:

$ node asynctest.js 
http://google.com
BEFORE
AFTER
INSIDE
200  Start: Sat Dec 29 2012 11:31:34 GMT-0500 (EST)  End: Sat Dec 29 2012 11:31:34 GMT-0500 (EST)
http://yahoo.com
BEFORE
AFTER
http://ninjaturtles.com
BEFORE
AFTER
INSIDE
200  Start: Sat Dec 29 2012 11:31:36 GMT-0500 (EST)  End: Sat Dec 29 2012 11:31:37 GMT-0500 (EST)
INSIDE
200  Start: Sat Dec 29 2012 11:31:35 GMT-0500 (EST)  End: Sat Dec 29 2012 11:31:38 GMT-0500 (EST)
于 2012-12-29T16:36:11.583 回答