В этом посте подробно описываются функции, используемые Earthquake Explorer , приложением Windows 8, которое отображает информацию о землетрясениях на картах Bing Earthquake Explorer был основан на стартовом наборе коллажей от Earthquakes на github . Прочитайте часть 1 здесь .
В первой части мы создали мобильную службу Windows Azure для хранения данных в качестве серверной части нашего гибридного приложения. Большим преимуществом этого подхода является то, что он позволяет нам фильтровать / сортировать / запрашивать данные любым удобным для нас способом, и наше приложение теперь устойчиво к сбоям и изменениям в схеме. В этой части мы собираемся изменить нашу существующую запланированную задачу, чтобы она использовала фактический поток данных USGS и сохранила его в таблице.
Получить данные просто благодаря замечательному каналу GeoJSON, предоставленному USGS. Подробнее об этом читайте здесь:
http://earthquake.usgs.gov/earthquakes/feed/v1.0/
Из нашей запланированной работы мы можем запросить ее следующим образом:
function fetchUSGS() {
console.log('Starting job');
var httpRequest = require('request');
var uri = 'http://earthquake.usgs.gov/earthquakes/feed/v0.1/summary/all_hour.geojson';
httpRequest(uri, function (err, response, body) {
if (err) {
console.warn('Error connecting to service.');
} else if (response.statusCode !== 200) {
console.warn('Unexpected reply.');
} else {
//got reply, process the results
var theData = JSON.parse(response.body);
processData(theData);
}
});
}
Мы делаем запрос к каналу (uri) и указываем обратный вызов в качестве встроенной функции. На самом деле не существует надежной обработки ошибок, но в действительности вы ничего не можете сделать в случае ошибки, кроме повторной попытки при следующем запуске задачи.
Вызов JSON.parse (), естественно, проанализирует текст ответа в хорошую коллекцию объектов, которую мы можем проанализировать. Если мы посмотрим на JSON в Fiddler, вы можете увидеть структуру документа:
JSON содержит коллекцию объектов, где каждый объект содержит объект геометрии, строку идентификатора и объект свойств. Либо с помощью документации на сайте USGS, либо путем изучения результатов, нам нужно знать структуру данных.
Чтобы сделать работу с данными немного проще, мы можем создать простой класс javascript для хранения данных:
function earthquake(item) {
this.latitude = item.geometry.coordinates[1];
this.longitude = item.geometry.coordinates[0];
this.depth = item.geometry.coordinates[2];
this.usgsId = item.id;
this.usgsCode = item.properties.code;
this.tz = item.properties.tz;
this.mag = item.properties.mag;
this.time = item.properties.time;
this.updated = item.properties.updated;
this.place = item.properties.place;
this.timestamp = new Date();
}
Здесь есть один сложный момент: идентификатором землетрясения является идентификатор USGS, но все данные в мобильных службах Azure используют bigint в качестве первичного ключа. Когда мы обновляем строку в Mobile Services, мы передаем объект в метод update с соответствующим идентификатором (bigint). (Для удаления требуется только идентификатор bigint.) Да, это небольшая неэффективность, поскольку WAMS использует суррогатный bigint, а USGS предпочитает естественный ключ идентификатора USGS, и для простоты мы будем использовать оба в зависимости от операции. Поскольку мы часто запрашиваем данные, каждый элемент в ленте будет иметь одно из нескольких состояний: он может быть новым (не в базе данных), он может быть уже в базе данных или в базе данных, но Фид содержит обновленные / пересмотренные значения.
function processData(json) {
var quakesTable = tables.getTable('earthquakes');
var featureList = json.features;
featureList.forEach(
function (item) {
var eq = new earthquake(item);
quakesTable.where({
usgsId: eq.usgsId
}).read({
success: function (results) {
if (results.length > 0) {
//record exists
eq.id = results[0].id;
eq.timestamp = new Date();
quakesTable.update(eq);
} else {
//record doesn't exist
quakesTable.insert(eq);
//send notification?
//see next blog post
}
}
});
}
);
}
As we iterate through the features, we create an earthquake object from each item. We then check the table for a record with the same USGS ID property. If it already exists, we’ll update the row with the information because details may have changed. Otherwise, we’ll insert it.
There’s a general inefficiency here that we can deal with if we’re so motivated. Each item results in a query to see if the item exists, and then a query to either update or insert. We could simply build a stored procedure that handles either scenario so it’s one call, but because each feed contains about 10 items and this scheduled task is a server-side job, it’s not high on my priority list. With higher volume apps and/or with client apps, this is a modification you should make.
The other nice thing we can do is send notifications when a new earthquake is found. For example, if a new earthquake is found in the feed, we can send a live tile notification which would update the tile to look like so:
For Windows 8 apps, this is really a must-do feature. Do _something_ (anything!) with the live tile – this will differentiate your app. Mobile Services can send notifications to Windows Phone, Windows 8, iOS, and Android, so this is a great way to take the app cross platform. In the next post, we’ll look at how to do a live tile update like the one above.