Спонсор: Microsoft
Опубликован: 26.12.2012 | Доступ: свободный | Студентов: 727 / 31 | Длительность: 06:22:00
Специальности: Программист
Лекция 7:

Доступ к данным и их отображение

< Лекция 6 || Лекция 7 || Лекция 8 >
Аннотация: Большинство приложений для Магазина Windows каким-то образом соединяются с сетью – новостные приложения регулярно получают свежую информацию из новостных каналов. Компьютерные игры могут публиковать сведения о достижениях игрока в списках лидеров, картографические приложения могут запрашивать изображения и инструкции с серверов. Разработчикам необходимо понимать, как запрашивается информация с веб-ресурсов, как их приложения могут обеспечивать эффект присутствия, быть подключенными (Connected Applications).

Цели обучения

Материалы к модулю Вы можете скачать здесь.

В этом модуле вы научитесь осуществлять доступ к данным веб-сервисов и выводить их в приложение, макет которого основан на сетке. Вы изучите функцию WinJS.xhr, которая упрощает асинхронное обращение к сервисам.

Начало

Вам будет необходимо решение Starter из \Module_7_Assets\Starter из предыдущего модуля.

Доступ к веб-ресурсам

Есть много типов различных веб-ресурсов, включая HTML-страницы, XML-файлы и веб-сервисы. Чтобы создать приложение, которое вы можете связать с данными веб-ресурсов, вы должны иметь доступ к этим ресурсам и запросить их информацию. Ниже в таблице приведены несколько различных типов веб ресурсов и данных, которые они предоставляют.

Несколько примеров веб ресурсов, доступ к которым может быть осуществлен при помощи XmlHttpRequest или xhr
Тип источника Пример URL Описание
HTML-страницы http://www.microsoft.com Самый обычный веб-ресурс – это веб-страница. Их создают, используя HTML; обычно они содержат лишь данные документов. Для получения этих данных вы должны разобрать HTML-документ
XML-данные http://msdn.microsoft.com/en-us/magazine/rss/default.aspx?z=z&all=1 XML-данные могут быть представлены в виде самостоятельных документов или источников данных. Например: RSS-каналы (Really Simple Syndication), которые обычно применяются для публикации обновлений контента – в блогах, новостных сайтах и так далее
Веб-сервисы https://en.wikipedia.org/w/api.php?action=query&list=allimages&format=xml&ailimit=10 Веб-сервисы обычно представлены базами данных, к которым можно обращаться с помощью запросов, получая от них данные в определенном формате. Существует множество форматов, однако, в наши дни наиболее распространенными являются XML и JSON

Упражнение: работа с веб-ресурсами с помощью браузера

Веб ресурсы, описанные выше, могут быть доступны при помощи стандартного веб-браузера и могут быть просмотрены в нем.

  1. Откройте веб-браузер.
  2. Введите ссылку из примеров ссылок в таблице сверху.

Обратите внимание, что данные запрашиваются и извлекаются при помощи тех же HTTP-технологий, что и веб страницы.

XmlHttpRequest

Ресурсы, доступные при помощи URL, могут быть получены WinRT-приложением с использованием объекта XmlHttpRequest. Библиотека WinJS определяет метод вызова XmlHttpReques – функцию WinJS.xhr.

Вот простой пример применения функции WinJS.xh r для запроса к RSS-каналам:

WinJS.xhr({ url: "http://msdn.microsoft.com/en-us/magazine/rss/default.aspx" })
    .done(function complete(result) {
        // Data downloaded.
        divOut.innerText = "Downloaded the data";
});

Так как WinJS.xhr работает асинхронно, вы используете функции then() и done() для обработки завершения запроса (подробнее об этом в "Работа с файлами" ).

Для просмотра краткого руководства пройдите по ссылке:

http://msdn.microsoft.com/en-us/library/windows/apps/hh868282.aspx

Чтобы просмотреть полную документацию для WinJS.xhr, нажмите на ссылку ниже:

http://msdn.microsoft.com/en-us/library/windows/apps/br229787.aspx

Сервисы REST

Representation State Transfer (REST) – "передача состояния представления" — модель представления данных, принятая в веб-сервисах.

REST работает поверх стандартных команд HTTP-протокола, которые обычно применяются для обеспечения функционирования HTML-страниц. Существует много сервисов, использующие REST. Например, Википедия предоставляет данные при помощи API (прикладного интерфейса программирования) MediaWiki, который пользуется REST.

Форматы извлечения данных из REST сервисов могут быть разными, но обычно это XML и JSON. XML легко читается и пользователями, и программами, однако, он может быть избыточным. Вот маленький пример данных XML:

<?xml version="1.0"?>
<api>
  <query>
    <allimages>
      <img title="File:!!!  !!! album cover.jpg" ns="6" 
descriptionurl=" https:\/\/en.wikipedia.org\album_cover.jpg" 
url=" https://upload.wikimedia.org\/wikipediaalbum_cover.jpg" 
timestamp="20100524T17:22:43Z" 
name="!!!__!!!_album_cover.jpg"/>
    </allimages>
  </query><querycontinue>
    <allimages aifrom="!Hero (album).jpg"/>
  </querycontinue>
</api>

JSON является менее избыточным, чем формат XML, данные в этом формате могут быть легко прочитаны (сериализовано и десериализовано) при помощи JavaScript. Вот маленький пример данных, представленных в JSON-формате:

{
 "query": {
  "allimages": [
   {
    "name": "!!!_-_!!!_album_cover.jpg",
    "timestamp": "2010-05-24T17:22:43Z",
    "url": https://upload.wikimedia.org\/wikipediaalbum_cover.jpg",
    "descriptionurl": "https:\/\/en.wikipedia.org\album_cover.jpg",
    "ns": 6,
    "title": "File:!!! - !!! album cover.jpg"
   }
  ]
 },
 "query-continue": {
  "allimages": {
   "aifrom": "!Hero (album).jpg"
  }
 }
}

Веб-сервисы поддерживают множество форматов. Например, Wikipedia API может возвращать результаты в XML, JSON и в других популярных форматах. Попробуйте перейти по ссылкам, приведенным ниже, чтобы увидеть, как различаются эти форматы.

Эти URL доступны в файле \Module_7_Assets\snippets\sampleURLs.txt

Примеры форматов возвращаемых данных Википедии

Пример: получаем список изображений при помощи Wikipedia API в формате XML

https://en.wikipedia.org/w/api.php?action=query&list=allimages&format=xml&ailimit=10

Пример: получаем список изображений при помощи Wikipedia API в формате JSON

http://en.wikipedia.org/w/api.php?action=query&list=allimages&format=jsonfm&ailimit=10

Работаем с JSON

Есть несколько преимуществ использования JSON как формата передачи для работы с веб-сервисами. Во-первых, JSON имеет более краткий формат вспомогательных данных. В примерах ниже вы увидите, что сообщение в формате JSON, намного компактнее XML. Это означает, что ответ может возвращаться быстрее, то есть говорит о лучшей производительности в приложениях. Во-вторых, с JSON очень легко работать в JavaScript. Вы можете преобразовывать строку JSON в объект JavaScript при помощи только одной команды – JSON.parse:

var myObject = JSON.parse(response);

Команда JSON.parse принимает на вход строку JSON и возвращает объект JavaScript. Вы также можете перевести объект JavaScript в строку JSON, используя функцию JSON.stringify.

var jsonString = JSON.stringify(myObject);

Упражнение: обращаемся к сервису

Создайте запрос к Wikipedia API, используя объект WinJS.xhr. Вы извлечете список изображений, совпадающих с некоторыми поисковыми строками, которые посвящены спорту: бейсболу, баскетболу и футболу.

  1. Откройте файл /js/data.js
  2. Найдите строки ниже и удалите их. Эти строки добавлены в качестве образцов данных, и вы замените эти образцы на ваши данные.
    // TODO: Replace the data with your real data.
    // You can add data from asynchronous sources whenever it becomes available.
    sampleItems.forEach(function (item) {
        list.push(item);
    });
    
  3. Когда вы удалите строки, добавьте следующий код, который определяет четыре категории данных.

    Этот код доступен в файле \Module_7_Assets\snippets\addGroups.txt

    var groupBasketball = { key: "Basketball", title: "Basketball", 
    subtitle: "Search results for Basketball", backgroundImage: "/images/groupBasketball.png", 
    description: "This group contains Wikipedia images for Basketball." };
    getBySearch(groupBasketball);
    
    var groupSoccer = { key: "Soccer", title: "Soccer", 
    subtitle: "Search results for Soccer", backgroundImage: "/images/groupSoccer.png", 
    description: "This group contains Wikipedia images for Soccer." };
    getBySearch(groupSoccer);
    
    var groupBaseball = { key: "Baseball", title: "Baseball", 
    subtitle: "Search results for Baseball", backgroundImage: "/images/groupBaseball.png",
     description: "This group contains Wikipedia images for Baseball." };
    getBySearch(groupBaseball);
    
    // Let's add in a Group for searching through the Search Charm later on!
    var groupSearch = { key: "Search", title: "Search", 
    subtitle: "Search results for Custom User Search", backgroundImage: "/images/groupSearch.png", 
    description: "This group contains Wikipedia images containing the user
  4. Далее, как только вы введете код, добавьте функцию getBySearch, которая направляет запрос к REST-сервису Википедии, передавая в качества типа поиска "allimages", и возвращает ответ в формате JSON. Для каждого найденного результата вызывается функиця getPage, которую вы добавите в следующем шаге.

    Этот код доступен в файле \Module_7_Assets\snippets\getBySearch.txt

    function getBySearch(group) {
        var search = group.title;
    
        // get a list of ALL IMAGES that contain the search string:
        WinJS.xhr({ url: "http://en.wikipedia.org/w/api.php?action=query&
    list=allimages&format=json&
    aiprefix=" + search + "&ailimit=4" })
            .then(function complQete(result) {
                var results = JSON.parse(result.response);
    
                // *NEXT* get a list of all FIRST PAGES that contain the IMAGE REFERENCE
                for (var i in results.query.allimages) {
                    var item = results.query.allimages[i];
                    getPage(item, list, group);
                }
            });
    
        return groupedItems;
    }
    
  5. Чуть ниже метода getBySearch добавьте getPage, который запрашивает REST-сервис Википедии для детальных данных страницы. Вы извлечете первую страницу, которая ссылается на изображение, найденное в getBySearch.

    Этот код доступен в файле \Module_7_Assets\snippets\getPage.txt

    function getPage(item, listAdd, group) {
            WinJS.xhr({ url: 
    "http://en.wikipedia.org/w/api.php?action=query&
    list=imageusage&format=json&iutitle=" + item.title + "&iulimit=20" })
            .then(function complete(result) {
                var firstPageInfo = JSON.parse(result.response);
    
                if (firstPageInfo.query.imageusage.length > 0) {
                    var pageId = firstPageInfo.query.imageusage[0].pageid;
    
                    // GET THE PAGE DETAILS FOR ALL PAGES
                    WinJS.xhr({ url: 
    "http://en.wikipedia.org/w/api.php?action=query&prop=revisions&
    format=json&rvprop=ids%7Ccontent&rvlimit=1&pageids=" + pageId })
                    .then(function complete(result) {
                        var firstpageContent = JSON.parse(result.response);
    
                        for (var j in firstpageContent.query.pages) {
                            var pageItem = firstpageContent.query.pages[j];
    
                            for (var k in pageItem.revisions[0]) {
                                if (k == "*") {
    
                                    var revision = pageItem.revisions[0][k];
                                    revision = wiky.process(revision);
    
                                    listAdd.push({ group: group, title: pageItem.title, 
    subtitle: item.name, description: item.name, content: revision, backgroundImage: item.url });
                                }
                            }
                        }
                    });
    
                }
                else {
                    // this image is NOT USED in any page yet, it just happens to exist on wikipedia. 
    So we'll add in some minimum info.
                    listAdd.push({ group: group, title: item.name, subtitle: item.name, 
    description: "There are currently no Wikipedia articles using this image.", 
    content: "There are currently no Wikipedia articles using this image.", backgroundImage: item.url });
    
                }
    
            });
        }
    
  6. В итоге, вы будете использовать утилиту JavaScript с открытым кодом, чтобы перевести данные из формата Wikimedia Text Format в HTML. Нажмите правой клавишей мыши подпапку JS и выберите Добавить существующий элемент (Add Existing Item). Откройте папку \Module_7_Assets\snippets\ subfolder и выберите wiky.js.
  7. Откроем файл default.html и добавим ссылку на wiky.js.
    <script src="/js/wiky.js"></script>
  8. Запустите проект и удостоверьтесь в том, что заполнение групп соответствует результатам запроса из Википедии.
  9. Нажмите на объект на первой странице и обратите внимание на то, что вы получили следующее необработанное исключение
    Установка атрибута innerHTML в какой-либо тип контента может вызвать исключение

    Установка атрибута innerHTML в какой-либо тип контента может вызвать исключение
  10. Это исключение возникает в указанной строке кода.

    Эта строка кода настраивает содержимое для описаний изображений, однако данные могут cодержать зарезервированный текст, который может быть интерпретирован как тег HTML или код JavaScript. В веб-клиенте данный код открывает возможность возникновения проблем безопасности, но в Windows 8 вы можете использовать специальную функцию – setInnerHTMLUnsafe, чтобы исключить подобные ошибки. Нам нужно только заменить код с исключением на вызов функции setInnerHTMLUnsafe.

    Этот код доступен в файле \Module_7_Assets\snippets\setInnerHTMLUnsafe.txt

    // We need to use set unsafe, because the HTML content contains some js tags!
    WinJS.Utilities.setInnerHTMLUnsafe(element.querySelector("article .item-content"),
    
  11. Запустите проект заново и попробуйте выделить объект. Обратите внимание на то, что теперь ошибка не возникает.

Итоги

Подключенное (connected) приложение может создавать эффект присутствия и держать пользователей в курсе последних новостей. В этом модуле вы изучили, как осуществлять запросы к веб-ресурсам, используя функции в WinJS, и как выводить эти данные в приложение, макет которого построен на основе сетки.

Самостоятельная работа

Wikipedia API предоставляет множество различных запросов для поиска в базах данных. Следующая ссылка дает доступ к среде безопасного выполнения (песочнице, sandbox) API, чтобы различные запросы можно было испытать в интерактивном режиме. Попытайтесь выполнить различные запросы к этому API, затем модифицируйте пример, которым вы занимались выше, таким образом, чтобы получить различные данные от сервиса. http://en.wikipedia.org/wiki/Special:ApiSandbox

Вопросы

  1. Вам необходимо вызвать веб-сервис и извлечь данные из результатов запроса. Какая функция WinJS может нам помочь выполнить эту задачу?
  2. Вы получаете результат запроса как строку JSON. Какую функцию JSON можно использовать для конверсии в объект JavaScript?
  3. Какой формат более эффективен с точки зрения размера: JSON или XML?

Дополнительные ресурсы

Вы можете узнать больше об этой теме из следующих ресурсов.

  • Краткое руководство: загрузка файла с помощью WinJS.xhr

    http://msdn.microsoft.com/ru-ru/library/windows/apps/hh868282.aspx

    Краткое руководство показывает как извлекать HTML с веб-страниц, используя WInJS.xhr.

  • Подключение к сетям и веб-службам

    http://msdn.microsoft.com/en-us/library/windows/apps/br211370.aspx

    Ссылки на различные статьи о том, как создать несколько типов подключенных приложений.

  • Краткое руководство: доступ к данным служб Live

    http://msdn.microsoft.com/en-us/library/windows/apps/hh920269.aspx

    Описание того, как приложения могут запрашивать пользовательскую информацию, такую, как календарь, контакты и информацию о профиле

Ответы

  1. ВМы можете использовать функцию WinJS.xhr для осуществления запросов к веб-сервисам.
  2. Функция JSON.parse может конвертировать строку JSON в объект JavaScript.
  3. Данные в формате JSON менее избыточены в плане размера передаваемой информации, чем XML.
< Лекция 6 || Лекция 7 || Лекция 8 >
Петр Василенко
Петр Василенко
Россия, Саратов, СГУ, 1973
Иван Пынин
Иван Пынин
Россия, Челябинск