node js - 写完后

时间:2015-07-26 14:55:40

标签: javascript node.js

我遇到了错误消息,即在write之后调用end。我的app.js看起来像这样:

var router = require('./router.js');

// Create a web server
var http = require('http');
http.createServer(function (request, response) {
  router.home(request, response);
  router.valuation(request, response);

}).listen(3000);
console.log('Server running.');

router.js的相关部分看起来像这样。

// Handle ticker valuation 
  function valuation(request, response) {

  var ticker = request.url.replace('/valuation/','');
  if (request.url === '/valuation/' + ticker) {

    if(ticker.length > 0) {
      response.writeHead(200, {'Content-Type': 'text/plain'});
      response.write('Header\n');
      scraper.roe(ticker, response);
      scraper.roic(ticker, response);
      response.end('Footer\n');

    }
  };

  // on 'error', show error

  //response.end('Error');
};

使用scraper.js模块并具有roe和roic功能的xray文件的相关部分如下所示:

//Get ROIC
function roic(ticker, response) {

    x('http://www.example.com/' + ticker + '/ROIC/', 'table.R10', [{

        table: x('td', [{
            date: x('tr:first-child td', 'strong'),
            roic: x('tr:nth-child(2) td', 'strong')

        }])


    }])(function(err, obj) {

        //Display only the first table, i.e. annual data. Slice quarterly data.
        obj = obj.slice(0, 1);
        obj = obj[0].table;

        response.write('On ' + obj[0].date + ' ' + ticker + '\'s ' + 'ROIC was ' + obj[10].roic + '\n');

        //response.end('Footer\n');

    })
};


//Get ROE
function roe(ticker, response) {

    x('http://www.example.com/' + ticker + '/ROE/', 'table.R10', [{

        table: x('td', [{
            date: x('tr:first-child td', 'strong'),
            roe: x('tr:nth-child(2) td', 'strong')

        }])


    }])(function(err, obj) {

        //Display only the first table, i.e. annual data. Slice quarterly data.
        obj = obj.slice(0, 1);
        obj = obj[0].table;

        response.write('On ' + obj[0].date + ' ' + ticker + '\'s ' + 'ROE was ' + obj[10].roe + '\n');

        //response.end('Footer\n');

    })


};

控制台日志(如果包含)适当地obj,但我没有在浏览器中看到输出,因为它返回上面提到的常见错误。另外,如果我取消注释response.end('Footer\n')roe函数中的roic部分,输出将起作用,但仅适用于一个函数,而不是两个或更多。

我很缺乏经验,因此如果有人可以在代码中提出结构更改以便允许我运行多个scraper函数 - 除了scraper.roe()scraper.roic()函数之后,我会很高兴竞赛在response.end()文件中运行router.js

我知道.on('end', fn() {})方法,但无法正确实现。

1 个答案:

答案 0 :(得分:0)

在您的代码中,

 scraper.roe(ticker, response);
 scraper.roic(ticker, response);
 response.end('Footer\n');

是同步执行的,但每次调用scraper都会在调用response.write之前对外部资源进行异步调用。

所以response.end确实总是被称为太早。

请注意,您目前还无法知道哪个结果(鱼子或者roic)将首先出现。

为了协调调用,您需要修改您的roe和roic函数,以便他们使用结果调用回调+使用String.CharacterView