Когда данные 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%2a%20from%20html%20where%20url%20=%20%22http://news.bbc.co.uk/weather/forecast/4276?&search=gerrards%2520cross&itemsPerPage=10®ion=world&area=Gerrards%2520Cross%22%20and%20xpath=%27//tbody%27&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.


person oshirowanen    schedule 05.07.2011    source источник
comment
Является ли ответ ниже единственным ответом на этот вопрос. Если нет, есть ли лучший ответ?   -  person oshirowanen    schedule 08.07.2011
comment
Код в try...catch только заменяет нулевое значение пустым значением. Это то, что вы хотите, или вам нужно какое-то другое значение, как объяснено в вопросе? Если да, то в следующем разделе temp min к чему относятся слова next и section?   -  person Guffa    schedule 12.07.2011
comment
Как вы пришли к выводу, что day.td[2].span[0].span.content становится null? Это утверждение, похоже, привело к тому, что половина ответов были не чем иным, как ответами на вопрос Как мне сделать довольно условное выражение?   -  person mercator    schedule 15.07.2011


Ответы (6)


Я могу констатировать очевидное, но почему бы просто не использовать оператор 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>");
}
person J. Ed    schedule 08.07.2011
comment
Очевидное легко не заметить. Я попробую это и дам вам знать. - person oshirowanen; 08.07.2011

Если вы Используйте консоль YQL, чтобы проверить полученный результат, и вы увидите, что весь td становится null. Так вот почему вы получаете ошибку.

Вы должны делать:

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

(Или в зависимости от того, как вы хотите выполнять условный вывод.)

Так уж получилось, что в Великобритании была ночь, когда я посмотрел на это, так что на самом деле я получил проблемный вывод. Но учитывая, что на этой странице можно найти прогноз погоды по всему миру, вы можете так же легко выбрать город в другом часовом поясе и использовать его для проверки.

person mercator    schedule 14.07.2011

Чтобы использовать минимальную температуру того же дня, измените это

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)

person nafisto    schedule 11.07.2011

Вы можете использовать оператор ||, чтобы заменить нулевое значение другим значением. Я не уверен точно, какое значение вы хотите, но это будет использовать значение на следующий день:

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>"
);
person Guffa    schedule 12.07.2011

Как упомянул sJhonny, вам просто нужно использовать оператор if. Загвоздка в том, что вам нужно знать, что на самом деле является нулевым, потому что следование указателю в любом месте после нулевого значения приведет к ошибке. Не зная подробностей возвращаемых данных, вы должны просто проверить все по очереди:

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). В любом случае вам, вероятно, следует проверять эти другие поля — вы можете защитить свой сайт от случайных ошибок, если какое-то другое поле данных окажется пустым в этом канале.

person Jason Striegel    schedule 14.07.2011

Я знаю, что это намного больше, чем вы, вероятно, хотели, но это действительно то, как я решил эту проблему.

Вместо того, чтобы получать JSON от веб-службы, здесь я бы рекомендовал получить HTML (пример запроса), так как вы используете 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);

}

Надеюсь это поможет!

person jimbo    schedule 05.07.2011
comment
К сожалению, это все еще не зависит от структуры, поскольку .temp.max .cent не существует в ночное время, поэтому вместо этого вы получаете только массив из 4 элементов и в конечном итоге помещаете данные в неправильные столбцы. - person mercator; 15.07.2011
comment
Да, я думал, ты можешь это сказать. Я постфактум понял, что так и будет. Я обновил пример, чтобы он работал как положено. - person jimbo; 16.07.2011