node.js reqest.js/cheerio.js 返回空 json

标签 node.js callback cheerio

我正在开发一个应用程序,该应用程序可以抓取网站并将数据作为休息 API 公开。我正在使用 Node、Express、request、cheerio。我似乎在数组中获得了正确的值..但在返回之前..数组仍然是空的(在请求函数范围之外)

我无法解决我所缺少的内容..您可以看一下我的代码并让我知道吗?

在app.js中我指定了路线,

    app.use('/timetable', timetable.timetable(url));

在 timetable.js 中

var classes = require('../lib/classes');
var schedule = require('../lib/schedule');
exports.timetable = function(timeTableURL) {

return function(req, res) {

    request( timeTableURL, function srapeWebsite(error, response, html ) {
        var webHtml = '';
        var moreInfo = []; 
        if( !error && response.statusCode === 200 ) {
            webHtml = cheerio.load(html);
        }
        // schedule.getInfo returns an array of json objects where
        // json = {
        //    day,
        //    number,
        //    url
        // }
        var info = schedule.getInfo(webHtml);

        for (var index = 0; index < info.length; index++) {     
            var json = info[index];
            classes.getMoreInfo(json, function (moreInfoJson) {
                //console.log shows correct information here
                moreInfo.push(moreInfoJson);
            };
        }
        // however moreInfo is empty here..hence not getting anything
        res.json(moreInfo);
    } );
  };
};

思路是,对于数组中的每个json对象,从指定的url中获取更多信息。

所以最终结果是,

    finalJson = {
       day : ''
       json : []
    }

在classes.js中

exports.getMoreInfo =  function (info, callback) {

var infoDay = info.day;
var infoNumber = parseInt(info.number);
var moreInfoURL = info.moreInfoUrl;
var stuff = [];

var moreInfo = {};
moreInfo.day = infoDay;
moreInfo.json = [];

if (infoNumber > 0 ) {
    request(moreInfoURL, function(error, response,html) {
        var moreInfoHtml = '';
        if( !error && response.statusCode === 200 ) {
            moreInfoHtml = cheerio.load(html) ;

        }
        var $ = moreInfoHtml;

        $('table tbody tr').each ( function getWhatisNeeded () {
            var json = getJson ( $(this) );
            stuff.push(json);

        });

        moreInfo.json = stuff;
        return callback(moreInfo);
    });
  }
}

最佳答案

您对classes.getMoreInfo 的调用是异步的。

发生的情况是,您没有等待调用返回,而是使用空数组调用 res.json。

编辑: 如何解决这个问题?一种方法是使用 promise (例如,参见 https://github.com/malko/D.js )。

getMoreInfo 应该返回一个延迟对象:

exports.getMoreInfo =  function (info) {
    var deferred = D();
    ...
    request(..., function(){
        deferred.resolve(moreInfo);
    });
    ...
    return deferred.promise;
}

和 timetable.js 应该看起来或多或少像这样:

var promises = [];
for (var index = 0; index < info.length; index++) {     
    var json = info[index];
    promises.push(classes.getMoreInfo(json));
}
D.all(promises).this(function(array_of_results){
    res.json(array_of_results);
}

我没有测试代码,所以这里可能有错误,但这是关于如何解决 Node.js 和一般情况下的异步问题的一个很好的指南。 让自己熟悉 Promise,解决这样的问题会容易得多。

关于node.js reqest.js/cheerio.js 返回空 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25499090/

相关文章:

c++ - 回调函数参数的 C++11 std::bind 和 auto 编译错误

javascript - 使用下面的 jquery ajax 缓存代码时,jquery ajax 中的回调不起作用

node.js - 是否可以使用 Cheerio 抓取 React 网站(Instagram)?

cheerio/jquery 选择器 : how to get text in tag a?

node.js - Electron 应用程序中的事件发射器内存泄漏

node.js - 为什么 client.on ("messageCreate"的 TextChannel 中缺少 nsfw 属性?

javascript - 为什么我的回调函数收到未定义的参数值?

javascript - 删除空 p 标记并将其他 p 标记转换为\n

node.js - bootstrap-datetimepicker 无法选择日期

javascript - 如何在 url 中发送 1 个以上参数以及如何在 Node.js/Express 的 GET 路由中访问它们