В этом посте подробно описываются функции, используемые 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.