当JSONP数据发生变化时

时间:2011-07-05 15:12:28

标签: javascript jquery json jsonp

更新1:

我可以通过try / catch来解决这个问题,但是当我知道问题是什么时,我宁愿不使用这个方法:

try {
    buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td>" + day.td[2].span[0].span.content + "</td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");
} catch(err) {
    buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td></td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");
}

原始问题:

使用以下jsonp服务:

http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%20%3D%20%22http%3A%2F%2Fnews.bbc.co.uk%2Fweather%2Fforecast%2F4276%3F%26search%3Dgerrards%2520cross%26itemsPerPage%3D10%26region%3Dworld%26area%3DGerrards%2520Cross%22%20and%20xpath%3D'%2F%2Ftbody'&format=json&callback=cbfunc22

我使用以下脚本来捕获数据:

$(document).ready(function() {
    get_bbc_weather();

    function get_bbc_weather() {
        $.ajax({
            url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%20%3D%20%22http%3A%2F%2Fnews.bbc.co.uk%2Fweather%2Fforecast%2F4276%3F%26search%3Dgerrards%2520cross%26itemsPerPage%3D10%26region%3Dworld%26area%3DGerrards%2520Cross%22%20and%20xpath%3D'%2F%2Ftbody'&format=json&callback=cbfunc22&rand=" + Math.random(),
            type: 'GET',
            dataType: 'jsonp',
            jsonp: 'callback',
            jsonpCallback: 'cbfunc22',
            error: function(xhr, status, error) {
                alert(xhr.responseText);
            },
            success: function(data) { 
                var buildHTML = [];

                var weather = data.query.results.tbody.tr;

                buildHTML.push("<tr><td>Day</td><td>Weather</td><td>Max<br />Day<br />(°C)</td><td>Min<br />Night<br />(°C)</td><td>Wind<br />(MPH)</td>");

                for (var i = 0; i < weather.length; i++) {
                    var day = weather[i];

                    buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td>" + day.td[2].span[0].span.content + "</td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");
                }

                $('#divContent1').empty().append("<table>" + buildHTML.join("</tr>") + "</table>")


            }
        });

    }

});

但是,在某一天的某个时间,day.td[2].span[0].span.content变为null。发生这种情况时,如何检测它并仅在第一天使用下一个temp min部分?其余时间应继续使用temp max部分。

6 个答案:

答案 0 :(得分:5)

我可能会在这里陈述显而易见的事,但为什么不使用if语句呢?

if (day.td[2].span[0].span.content != null) {
    buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td>" + day.td[2].span[0].span.content + "</td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");
} 
else {
    buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td></td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");
}

答案 1 :(得分:2)

如果您use the YQL console to examine the output you're getting,您会看到整个td变为null。这就是你收到错误的原因。

你应该这样做:

if (day.td[2] == null)

(或者你喜欢用条件输出的方式。)

碰巧看到它在英国的那个夜晚,所以我实际上得到了有问题的输出。但鉴于that page可以为您找到世界各地的天气预报,您可以轻松地在其他时区选择一个城市并使用它来测试它。

答案 2 :(得分:1)

我知道这比你想要的要多得多,但这确实是我解决这个问题的方式。

不是从Web服务中获取JSON,而是建议获取HTML(example request),因为您使用的是jQuery并且它提供了一个很好的搜索机制 - 而不是自己遍历结构并运行当结构发生变化时陷入困境。

这是我以与结构无关的方式生成您正在制作的同一个表的代码。我遗漏了所有的ajax部件,因为它们保持不变。这只是成功的处理程序。

function success(data) {

  var

    $data = $('<table></table>')
      .html(data.results[0]),

    $table = $(
      '<table>' +
        '<thead>' +
          '<tr>' +
            '<th>Day</th>' + 
            '<th>Weather</th>' + 
            '<th>Max<br />Day<br />(°C)</th>' + 
            '<th>Min<br />Night<br />(°C)</th>' + 
            '<th>Wind<br />(MPH)</th>' +
          '</tr>' +
        '</thead>' +
        '<tbody></tbody>' +
      '</table>'
    ),

    $tbody = $table.find('tbody');

  $data
    .find('tr')
    .each(function(index, tr){

      var

        $input = $(tr),
        $output = $('<tr></tr>')
          .appendTo($tbody),

        selectors = [
          '.slotname abbr',
          '.summary p',
          '.temp.max .cent',
          '.temp.min .cent',
          '.wind .mph'
        ],
        i = selectors.length,

        text,
        $cell;

      while (i--) {
        $('<td></td>')
          .text(
            $input
              .find(selectors[i])
              .text()
          )
          .prependTo($output);
      }

    });

  $('#divContent1')
    .empty()
    .append($table);

}

希望这有帮助!

答案 3 :(得分:1)

要使用同一天的最小温度,请更改此

day.td[2].span[0].span.content

到这个

(day.td[2].span[0].span.content == null ? day.td[3].span[0].span.content : day.td[2].span[0].span.content)

如果这仍然引发异常,您需要确定day.td[2].span[0].span.content的哪一部分返回为空,即您可能需要检查day.td[2].span[0] == null

修改:要明确,您的陈述将如下所示:

buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td>" + (day.td[2].span[0].span.content == null ? day.td[3].span[0].span.content : day.td[2].span[0].span.content) + "</td><td>" + day.td[3].span[0].span.content + "</td><td>" );

此外,如果您只想让该单元格为空(而不是使用最大临时值),请使用:

(day.td[2].span[0].span.content == null ? "" : day.td[2].span[0].span.content)

答案 4 :(得分:1)

您可以使用|| opreator将null值替换为其他值。我不确定你想要什么价值,但这会使用第二天的价值:

buildHTML.push(
  "<tr>" +
  "<td>" + day.td[0].div.abbr.content + "</td>" +
  "<td><img src='" + day.td[1].div.div.img.src + "' /></td>" +
  "<td>" + (day.td[2].span[0].span.content || weather[i+1].td[2].span[0].span.content) + "</td>" +
  "<td>" + day.td[3].span[0].span.content + "</td>" +
  "<td>" + day.td[4].span[0].span[1].content + "</td>"
);

答案 5 :(得分:1)

正如sJhonny所提到的,你只需要使用if语句。问题是你需要知道什么实际上是null,因为跟随指针经过空值后,任何地方都会给你一个错误。如果不知道您收到的数据的详细信息,您应该能够检查所有内容:

var td2 = "";
if ( day.td[2] != null && day.td[2].span != null && day.td[2].span.length > 0 && day.td[2].span[0] != null && day.td[2].span[0].span != null && day.td[2].span[0].span.content != null ) {
    td2 = day.td[2].span[0].span.content;
}

buildHTML.push( "<tr><td>" + day.td[0].div.abbr.content + "</td><td><img src='" + day.td[1].div.div.img.src + "' /></td><td>" + td2 + "</td><td>" + day.td[3].span[0].span.content + "</td><td>" + day.td[4].span[0].span[1].content + "</td>");

当然,如果您知道哪个字段专门设置为null,则可以简化if语句。我不会担心使用try / catch,如果这使你的代码更清晰(在这种情况下,我认为我更喜欢try / catch,我自己)。无论哪种方式,您可能应该检查其他字段 - 您可以保护您的网站免受随机错误的影响,因为该Feed中某些其他数据字段恰好为空。