Давным-давно, во времена Web 1.0, веб-сайты были контейнерами контента для чтения и ничем иным. Когда умами разработчиков овладела Web 2.0, веб-сайты стали превращаться в онлайновые сервисы с API, используемыми программистами для комбинирования компонентов, данных и функциональности. Теперь гибридные приложения (mashups) позволяют разработчикам обращаться к богатым библиотекам контента без издержек размещения данных в собственных серверных помещениях.
С появлением Windows Runtime (WinRT) вы можете перенести мощь гибридных приложений в свое следующее приложение Windows Store. Управляете вы данными с помощью XmlHttpRequest (XHR) или выполняете аутентификацию в удаленном сервисе через класс WebAuthenticationBroker, Windows Library for JavaScript (WinJS) и Windows Runtime дают возможность легко включать онлайновые сервисы в ваше приложение.
Contoso Photo Finish
В этой статье я намерен создать гибридное приложение под названием «Contoso Photo Finish». Оно позволяет любителям бега отслеживать, сколько миль они пробежали, и публиковать снимки со своих пробежек. Многие «бегуны» любят делиться в социальных сетях такой информацией, как расстояние и места их пробежек. Contoso Photo Finish дает возможность рассказывать друзьям в Facebook о таких пробежках с комментариями и снимками. Это приложение будет подключаться к двум сервисам:
- Windows SkyDrive — для получения снимка с пробежки;
- Facebook — для публикации снимка друзьям.
Contoso Photo Finish будет комбинировать эти сервисы, обеспечивая пользователю постоянное подключение к социальной сети. В этой статье предполагается, что у вас есть Visual Studio 2012 и что в нем открыт шаблон JavaScript | Windows Store | Blank App, готовый к тому, чтобы начать кодирование.
Барьеры гибридного приложения: аутентификация и авторизация
Если приложение (для Windows Store или Web) должно публиковать контент в Facebook, первый барьер, который ему придется преодолеть, — аутентификация. Facebook нужно знать, кто подключается к нему. Когда пользователи пытаются входить в приложения, они предъявляют свою идентификацию (обычно в виде имени пользователя) и удостоверение (например, пароль, маркер защиты, данные от устройства биометрической защиты и т. д.), чтобы доказать, что они должны получить доступ к запрошенной идентификации. Аутентификация — это процесс проверки идентификации пользователя на основе удостоверения.
После аутентификации пользователя у гибридного приложения появляется следующая трудная задача: определение того, что именно этот пользователь может делать в системе. Авторизация — это процесс, в ходе которого разрешаются или запрещаются определенные действия на основе некоего атрибута или членства в одной из ролей безопасности. Например, в Twitter моей идентификации запрещено удалять все твиты любых пользователей. Я не авторизован на выполнение такого действия, так как я не являются членом роли безопасности с соответствующим разрешением. Совместно аутентификация и авторизация (A&A) представляют вопрос: пользователь, кто ты и что ты имеешь право делать?
В гибридных приложениях эти задачи усложняются, потому что разработчик, создающий такое приложение, не имеет доступа к тому месту, где хранятся идентификации, удостоверения и роли безопасности (зачастую его называют хранилищем удостоверений). Поэтому, если я не могу проверить, кто есть кто и что они могут делать, то как же я создам гибридное приложение для таких приложений, как Facebook? OAuth спешит на помощь!
OAuth: доступ к ресурсам, а не к приложениям
OAuth рассчитан на решение проблем A&A для гибридных приложений (получающих информацию из разнородных источников). Вообразите, что App X хочет получить доступ к контенту от Online Service Y. Вместо аутентификации пользователя в App X происходит его аутентификация в Online Service Y, так как удостоверения пользователя хранятся в соответствующем хранилище Online Service Y. Затем пользователь разрешает App X обращаться к указанным ресурсам Online Service Y в течение ограниченного времени. Разрешение на доступ к ресурсам Online Service Y возвращается App X как маркер доступа (иногда его называют просто маркером).
В традиционных веб-моделях A&A права доступа пользователя определяются двумя участниками: приложением и пользователем (или сервером и клиентом). В OAuth введен третий участник: сервер ресурсов. Серверы ресурсов являются третьими сторонами, хранящими некий ресурс (например, фотографии) на сервере, к которому нужно обратиться клиенту. В Contoso Photo Finish в роли сервера ресурсов выступает Facebook. Ресурс, к которому нужно обращаться Contoso Photo Finish, — статус пользователя; это требуется для публикации сообщения.
Клиенты OAuth и процессы их аутентификации
В OAuth существует два типа клиентов, и какой тип следует использовать, определяется уровнем доверия к клиенту. Конфиденциальные клиенты (confidential clients) могут хранить свои удостоверения защищенными и предназначены для сред с высоким доверием. Примеры конфиденциальных клиентов — веб-приложения на серверной стороне, где секрет клиента может храниться в контролируемой безопасной среде. Конфиденциальные клиенты используют процесс Authorization Code для получения маркера защиты, передавая секрет клиента серверу ресурсов; этот секрет служит средством аутентификации клиента.
Общедоступные клиенты (public clients) не могут хранить свои удостоверения защищенными, так как они выполняются во враждебной среде. Примеры таких клиентов — приложения пользовательских агентов (т. е. веб-приложения на JavaScript) или неуправляемые приложения (вроде приложений Windows Store). Общедоступные клиенты использую процесс «неявной выдачи разрешений» («implicit grant») для получения маркера защиты, поскольку секрет клиента нельзя безопасно хранить во враждебной среде, контролировать которую разработчик не может.
Приложения Windows Store можно конфигурировать либо на процесс неявной выдачи разрешений, либо на процесс генерации кода авторизации для OAuth (подробнее об этих процессах см. по ссылке bit.ly/yQjyQZ). С точки зрения безопасности, рекомендуется всегда применять неявную выдачу разрешений, если приложение размещается в неконтролируемой разработчиком среде.
На рис. 1 я привел схему процесса неявной выдачи разрешений, где клиент начинает переговоры в попытке определить идентификацию пользователя для сервера ресурсов.
Рис. 1. Переговоры при неявной выдаче разрешений для приложения Windows Store
1. User, please identify yourself to the resource server. | 1. Пользователь, пожалуйста, идентифицируйте себя серверу ресурсов |
2. Hello, Facebook, I’m John. Here are my credentials. | 2. Привет, Facebook, я — Джон. Вот мои удостоверения |
3. Thanks, John. App, here’s an access token. | 3. Спасибо, Джон. Приложение, держи маркер доступа |
4. Thanks, Facebook. John, I can now connect to the Facebook API on your behalf! | 4. Спасибо, Facebook. Джон, теперь я могу соединиться с Facebook API от твоего имени! |
App (Client) | Приложение (клиент) |
User | Пользователь |
Facebook (Resource Server) | Facebook (сервер ресурсов) |
Этапы, приведенные на рис. 1, поясняются ниже.
- Приложению Windows Store нужно выполнить некую функциональность, которая требует доступа к Facebook API.
- Пользователь подключается к серверу ресурсов по URI, который включает информацию о приложении Windows Store, пытающемся получить доступ к Facebook API. Эти данные обычно передаются в виде идентификатора приложения или идентификационного кода клиента. Пользователь предоставляет имя и пароль для входа в Facebook.
- Предполагая успешный вход, Facebook предоставляет приложению Windows Store маркер доступа.
- Теперь приложение Windows Store, применяя маркер доступа от Facebook, может предоставить пользователю данные от Facebook API и передавать пользователю комментарии, публиковать снимки и т. д.
Эти «переговоры» осуществляются на удивление легко благодаря использованию нового пространства имен Windows.Security.Authentication.Web.
WebAuthenticationBroker
В приложениях Windows Store класс WebAuthenticationBroker (bit.ly/RW8czT) является компонентом, который будет взаимодействовать с сервером ресурсов, предоставлять элементы управления входом и реагировать на успешный вход; при этом приложению Windows Store не требуется ничего знать об удостоверениях пользователя. В нашем примере Contoso Photo Finish нужно публиковать снимки в Facebook. Для этого пользователь должен аутентифицироваться в Facebook и получить маркер доступа.
Добавьте в проект Contoso Photo Finish новый элемент управления «страница» (page control) —input.html. По умолчанию Visual Studio генерирует для вас большой объем разметки. Замените «<p>Content goes here.</p>» в разделе контента Main следующей кнопкой:
<input type="button" id="btnAddRun" value="Add Run" />
Это кнопка, щелкнув которую, пользователь добавит сведения о пробежке в Photo Finish. Теперь откройте input.js и вставьте такую функцию:
function btnAddRun_Click(e) {
var facebookOauthUrl = "https://www.facebook.com/dialog/oauth";
var facebookClientId = "[YOUR CLIENT ID]";
var redirectUrl = "https://www.facebook.com/connect/login_success.html";
var requestUri = Windows.Foundation.Uri(facebookOauthUrl +
"?client_id=" + facebookClientId +
"&redirect_uri=" + encodeURIComponent(redirectUrl) +
"&response_type=" +
"token&scope=read_stream,publish_actions&display=popup");
var callbackUri = Windows.Foundation.Uri(redirectUrl);
// Сюда помещается брокер веб-аутентификации
}
Этот код устанавливает переменные, которые будут использоваться в запросе аутентификации. Первая переменная — URL Facebook-сервиса OAuth. ClientId — это идентификатор приложения, используемый Facebook для определения Contoso Photo Finish как приложения, с которым будет взаимодействовать Facebook API. Такого рода идентификатор обычно присваивается приложению, когда оно регистрируется на сервере ресурсов. На некоторых серверах ресурсов требуется идентификатор клиента, приложения или просто идентификатор. Какой идентификатор нужно использовать, указывается в документации на API сервера ресурсов.
Параметр redirectUrl определяет, куда будет направлено приложение после аутентификации пользователя и разрешения приложению доступа к заданным ресурсам. В нашем случае redirectUrl задается в соответствии со стандартом Facebook, доступным всем приложениям Facebook API. Некоторые сервисы требуют идентификации URI приложения Windows Store на сервере ресурсов при его регистрации. URI приложения можно найти методом getCurrentApplicationCallbackUri брокера веб-аутентификации. Он вернет URI локального контекста приложения (начинающийся с «ms-app://»). Некоторые серверы ресурсов не поддерживают ms-app:// в качестве допустимого протокола для redirectUrl, и в таком случае вы должны делать проверку на адрес перенаправления по умолчанию.
Далее определяется callbackUri. Это адрес, информирующий брокер веб-аутентификации о завершении аутентификации и возврате управления приложению Windows Store. На самом деле брокер никогда не переходит по этому URL; он просто отслеживает момент, когда сервер ресурсов вызывает эту страницу, а затем возвращает callbackUri с любой строкой запроса или параметрами хеша, которые были дописаны в конец этого параметра. В данном случае параметр хеша access_token предоставит Contoso Photo Finish маркер, необходимый для взаимодействия с API.
Класс WebAuthenticationBroker используется метод authenticateAsync для подключения и выполнения процесса аутентификации на сервере ресурсов. При вызове authenticateAsync приложение открывает всплывающее окно, в котором отображается экран входа на сервер ресурсов (рис. 2). Как только аутентификация завершается или обнаруживается callbackUri, это окно закрывается.
Рис. 2. Всплывающее окно входа на сервер ресурсов из authenticateAsync
Ключевое преимущество использования этого окна в том, что приложение Windows Store никогда не обрабатывает и ничего не знает об удостоверениях пользователя для диспетчера ресурсов. Все, что известно приложению, — это маркер доступа, возвращаемый сервером ресурсов. Такое разделение обеспечивает изоляцию удостоверений для сервера ресурсов от приложения, что предотвращает риски для безопасности, неизбежные при хранении удостоверений в приложении. Помимо преимуществ в безопасности, разработчику не приходится писать какой-либо код для получения этого интерфейса; он встроен в метод authenticateAsync.
Теперь вернемся к коду. Замените комментарий «Web authentication broker will go here» следующим кодом:
Windows.Security.Authentication.Web.WebAuthenticationBroker.
authenticateAsync(Windows.Security.Authentication.Web.
WebAuthenticationOptions.none, requestUri, callbackUri)
.done(
function (result) {
// Здесь проверяйте состояние ответа
},
function (ex) {
Log(ex);
}
);
Метод authenticateAsync принимает три параметра (третий параметр не обязательный).
- WebAuthenticationOptions: Предоставляет инструкции брокеру веб-аутентификации о том, как визуализировать диалог аутентификации или какие данные следует возвращать в ответе. В предыдущем примере приложение использовало «none» для отображения универсальной реализации, которая не передает никаких параметров брокеру, и тот применяет настройки по умолчанию.
- requestUri: Это точка для входа на сервер ресурсов. В данном случае Contoso Photo Finish подключается к Facebook-сервису OAuth. При этом требуется защищенное соединение с применением протокола HTTPS.
- callbackUri: Это страница, при переходе на которую управление возвращается обратно брокеру веб-аутентификации, как было описано ранее. Данный аргумент не обязателен, но, если сервер ресурсов не может (или не хочет) перенаправлять в ms-app://, он определяет, как приложение может выходить из-под контроля сервера ресурсов. Например, в предыдущем коде, когда после успешного входа осуществляется переход на https://www.facebook.com/connect/login_success.html, брокер веб-аутентификации получит управление приложением от сервера ресурсов, закрыв диалог аутентификации и обработав успешное завершение аутентификации. CallbackUri не обязательно должен указывать немедленный переход на следующую страницу; такой переход мог бы происходить после выполнения какого-либо мастера или другого процесса на сайте сервера ресурсов. Обычно этот URI идентичен redirectUrl, но дает возможность расширения процесса аутентификации, если это необходимо.
Если брокер веб-аутентификации подключается к серверу ресурсов, вход считается успешным. Результат процесса аутентификации определяется через свойство ResponseStatus объекта WebAuthenticationResult. В предыдущем коде аргумент result — это объект WebAuthenticationResult с тремя свойствами: ResponseData (данные от сервера ресурсов), ResponseErrorDetail (описание ошибки, если что-то пошло не так) и ResponseStatus (состояние аутентификации). Замените комментарий «Check the response status here» на код, показанный на рис. 3.
Рис. 3. Работа с результатом процесса аутентификации
switch (result.responseStatus) {
case Windows.Security.Authentication.Web.WebAuthenticationStatus.success:
var fragment = Windows.Foundation.Uri(result.responseData).fragment;
if (fragment.indexOf("#access_token=") != -1) {
var token = fragment.substring(
new String("#access_token=").length,
fragment.indexOf("&expires_in="));
// Сюда добавляйте вызовы API
}
break;
case Windows.Security.Authentication.Web.WebAuthenticationStatus.userCancel:
Log(window.toStaticHTML(result.responseData));
Display("User cancelled the authentication to Facebook.");
break;
case Windows.Security.Authentication.Web.WebAuthenticationStatus.errorHttp:
Log(window.toStaticHTML(result.responseData));
Display("An error occurred while communicating with Facebook.");
break;
}
В коде на рис. 3 проверяется каждое состояние, причем метод Log записывает информацию от сервера ресурсов, а метод Display сообщает пользователю, что происходит. В случае ошибок не забывайте выводить пользователю сообщения с внятным описанием. Если аутентификация успешна, фрагмент URI, возвращенного Facebook, разбирается и сохраняется в переменной token для использования в API-вызовах (детали реализации см. в разделе «Получение и публикация информации через XHR»).
Написав функцию btnAddRun_Click, подключите ее к объекту btnAddRun в функции WinJS.UI.Pages.define{ready}:
var btnAddRun = document.getElementById("btnAddRun");
if (null != btnAddRun)
btnAddRun.addEventListener("click", btnAddRun_Click, false);
К этому моменту у приложения имеется маркер доступа, указывающий, что пользователь аутентифицирован на сервере ресурсов. В последнем разделе этой статьи я покажу, как приложение выполняет API-команды для отправки данных, но для начала приложению нужно получить то, что оно будет отсылать в Facebook.
Получение снимка
Windows 8 поддерживает множество контрактов, позволяющих приложениям взаимодействовать друг с другом, в частности запрашивать поиск, обмениваться данными и использовать средство выбора файлов (file picker). С помощью этих контрактов любое приложение можно превратить в гибридное (mashup), написав всего несколько строк кода. Contoso Photo Finish будет использовать возможности контракта выбора файлов, чтобы находить изображение для забега пользователя.
Одна из многих вещей, которые нравятся мне в Windows Phone, — интеграция со SkyDrive. Я могу моментально загружать в это облачное хранилище свои фотоснимки, чтобы в следующий раз, когда я снова сломаю свой смартфон (а такое у меня бывает часто), мои снимки ждали меня в хранилище. Приложение SkyDrive для Windows 8 предоставляет данные средству выбора файлов и тем самым делает выбор файлов с учетной записи SkyDrive не сложнее их выбора из библиотеки изображений. Следующая часть гибридного приложения Contoso Photo Finish будет использовать данные от приложения SkyDrive через средство выбора файлов. Для этого в input.html нужны некоторые, гм… элементы управления вводом (inputs).
Замените кнопку btnAddRun кодом, показанным на рис. 4. Этот код включает поля ввода, через которые пользователь предоставляет контент для Contoso Photo Finish. Кнопка btnSelectPhoto будет использовать средство выбора файлов для получения нужного файла изображения. Добавьте новую функцию в input.js, которая будет обработчиком события click для btnSelectPhoto:
function btnSelectPhoto_Click(e) {
var imgSelectedPhoto = document.getElementById("imgSelectedPhoto");
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.fileTypeFilter.replaceAll([".jpg", ".jpeg", ".png"]);
filePicker.suggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
filePicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
// Здесь выбирается файл
}
Рис. 4. Поля ввода, через которые предоставляется контент приложению
<p>
<label>Distance</label>
<input type="number" min="0" max="15" id="txtDistance"
required /> miles
</p>
<p>
<label>Comment</label>
<input type="text" min="0" max="15" id="txtComment" />
</p>
<p>
<label>Photo</label>
<input id="btnSelectPhoto" value="Select Photo" type="button" />
<img src="" id="imgSelectedPhoto" alt="Selected Photo" />
</p>
<p>
<input type="button" id="btnAddRun" value="Add Run" />
</p>
Функция начинает с подготовки переменной imgSelectedPhoto, которая будет использоваться для отображения выбранного снимка пользователю. Далее код создает объект выбора файлов (file picker object). Этот объект позволяет Contoso Photo Finish выбирать файлы или папки (в данном случае — файлы) в системе или других приложениях, участвующих в контракте выбора файлов, для открытия или взаимодействия внутри приложения. Применяя фильтр типов файлов, код ограничивает расширения файлов, доступные средству выбора. Приложение по своей архитектуре может загружать изображения только в Facebook, поэтому ограничение средства выбора работой лишь с определенными типами файлов изображений избавляет пользователя от вероятности выбора файла с непригодными для данных целей расширениями, которые не отвечают требуемой функциональности. Кроме того, из-за концентрации приложения на изображениях начальным местом для средства выбора файлов сделана библиотека изображений. Места по умолчанию могли бы быть самыми разнообразными (например, библиотеки музыки или документов, домашняя группа и др.), но при операциях только с картинками здравый смысл подсказывает, что начальной точкой должна быть библиотека изображений. Последнее, что нужно сделать для средства выбора файлов, — установить viewMode в thumbnail. Тогда при выборе изображений показываются их миниатюры (эскизы), что облегчает поиск нужной картинки.
Задав все параметры, можно выбирать файл, который будет использовать для данного забега. Сначала добавьте следующие объявления двух переменных сразу под выражением use strict:
var selectedPhotoStream = null;
var selectedPhotoFile = null;
В них будут храниться файл и связанный с ним поток для функции btnAddRun_Click при загрузке данных в Facebook. Теперь замените комментарий «Pick file here» кодом, показанным на рис. 5.
Рис. 5. Выбор файла
filePicker.pickSingleFileAsync().then(
function (storageFile) {
if (storageFile) {
selectedPhotoFile = storageFile;
selectedPhotoFile.openAsync(
Windows.Storage.FileAccessMode.read).then(
function (stream) {
selectedPhotoStream = stream;
document.getElementById("imgSelectedPhoto").src =
URL.createObjectURL(selectedPhotoFile);
},
function (ex) {
Log(ex);
Display("An error has occurred while reading the file.");
});
}
else {
Display("File was not selected");
}
});
Кажется, что на рис. 5 слишком много кода, но все сводится к трем операциям:
- выбор файла, который будет использоваться приложением через объект выбора файлов (pickSingleFileAsync);
- открытие файлового потока для чтения (openAsync);
- сохранение потока и файла в переменных для последующего применения.
Весь этот код является стандартным для работы с файлами и потоками за одним исключением: URL.createObjectURL принимает объект и формирует URL для объекта, который должен отображаться через объект изображения. Метод createObjectURL работает с объектами многих типов, в том числе Stream, StorageItem и MediaCapture. Как правило, он применяется при отображении медийного контента (изображения, аудио или видео) в приложении Windows Store. Используя createObjectURL помните, что по окончании работы с этим URL вы должны удалить его методом URL.revokeObjectURL. Это гарантирует оптимальное использование памяти и предотвращает засорение приложения Windows Store множеством временных URL. Подробнее о createObjectURL см. в документации MSDN по ссылке bit.ly/XdhzOm.
Наконец, сопоставьте событие btnSelectPhoto_Click с объектом btnSelectPhoto. Добавьте следующий код в функцию WinJS.UI.Pages.define{ready}:
var btnSelectPhoto = document.getElementById("btnSelectPhoto");
if (null != btnSelectPhoto)
btnSelectPhoto.addEventListener(
"click", btnSelectPhoto_Click, false);
К этому моменту в Contoso Photo Finish появляется контент, а у меня имеется механизм аутентификации в Facebook для его публикации. Теперь приложение должно просто взаимодействовать с API и передавать контент.
Получение и публикация информации через XHR
Помните, что было, когда AJAX был новинкой? Состоялся дебют XHR в Internet Explorer 5.5 и заставил веб-разработчиков заново продумывать, как делать веб-страницы. Прошло время, AJAX оброс множеством различных библиотек (например, jQuery) и превратился в легко воспринимаемое и (что важнее) простое в реализации решение. WinJS.xhr продолжает эту традицию простым API для получения и отправки данных в онлайновые сервисы.
Вернемся к функции btnAddRun_Click и заменим комментарий «Add API calls here» кодом, показанным на рис. 6.
Рис. 6. Генерация большого двоичного объекта (Blob) из selectedPhotoStream
var fileBlob = MSApp.createBlobFromRandomAccessStream(
selectedPhotoFile.contentType,
selectedPhotoStream);
var message = "I just ran " + document.getElementById(
"txtDistance").value + " miles with PhotoFinish! " +
document.getElementById("txtComment").value;
var data = new FormData();
data.append("source", fileBlob);
data.append("filename", selectedPhotoFile.name);
data.append("access_token", token);
data.append("message", window.toStaticHTML(message));
WinJS.xhr({
type: "POST",
url: "https://graph.facebook.com/me/photos",
data: data,
}).then(
function (photoid_response) {
ProcessResponse(photoid_response);
},
function (ex) {
Display("An error occurred while posting the photo.");
Log(ex);
});
Ранее приложение сохранило StorageFile и Stream в переменных selectedPhotoFile и selectedPhotoStream. MSApp.createBlobFromRandomAccessStream принимает selectedPhotoStream и генерирует Blob-объект (bit.ly/Stfu9z), который впоследствии передается приложением в Facebook как POST-параметр. Это полезная функциональность для преобразования WinRT-объектов в формат, который можно передавать по HTTP.
Далее код использует объект FormData (новинка в HTML5) для создания параметров, которые будут передаваться в HTTP POST. FormData — это объект с парами «ключ-значение» и всего одним методом: append. Используя метод append, разработчики могут динамически создавать поля формы и передавать их с POST так, будто было вызвано событие передачи формы. FormData также предоставляет параметры так, словно они принадлежат форме с кодированием multipart/form-data. Это позволяет разработчикам передавать целевому серверу любой тип ввода (включая файлы).
Заметьте, что в вызове метода FormData.append я использую toStaticHTML (bit.ly/ZRKBka), чтобы обеспечить безопасную доставку контента сообщения. Применение toStaticHTML приводит к удалению всех атрибутов события или контента скрипта из переменной message до ее добавления в объект FormData. Хотя Facebook довольно хорошо предотвращает атаки с применением кросс-сайтовых скриптов (по сравнению с другими социальными сетями), как разработчик гибридного приложения я хочу предоставлять чистый контент приложениям своих друзей. Интернет велик, поэтому всем нам надо присматривать друг за другом.
Остальной блок кода — вызов WinJS.xhr. На этот раз код использует некоторые дополнительные атрибуты XHR, в том числе:
- type: указывает HTTP-метод, который нужно применять. По умолчанию type задается как GET. В этом коде используется POST, потому что приложение посылает контент в Facebook API;
- data: содержит параметры, которые должны передаваться с POST.
После возврата promise в методе success приложение Contoso Photo Finish обрабатывает идентификатор снимка для его получения впоследствии. Если происходит ошибка, отображается стандартное сообщение об ошибке и в журнале регистрируется исключение.
WinJS.xhr во многом похож на другие оболочки XHR. Если вы знакомы с такими библиотеками JavaScript, как jQuery, вы сможете легко разобраться в WinJS.xhr. Один из подвохов, с которыми вы можете столкнуться, заключается в том, что в отличие от XHR в методе WinJS.xhr нет параметра timeout. Задание времени ожидания осуществляется обертыванием вызова WinJS.xhr в метод WinJS.Promise.timeout (bit.ly/Qgtx7a). Добавив следующий код в начало вызова WinJS.xhr, я задаю для POST время ожидания 10 секунд:
WinJS.Promise.timeout(1000, WinJS.xhr({ ... });
Если WinJS.xhr promise не выполняется в течение 10 секунд, этот promise считается просроченным и обрабатывается функцией error для тайм-аута promise.
Первые шаги в гибридизации вашего приложения
В этой статье я рассмотрел аутентификацию, получение файлов и отправку данных с помощью WinJS и Windows Runtime. Эти базовые навыки обязательны для разработки приложений Windows Store, возможности которых ограничены лишь вашим воображением и квалификацией. Возьмите материал этой статьи за основу и исследуйте свой любимый онлайновый сервис. Используя WinJS.xhr, ваше приложение Windows Store может взаимодействовать с бесчисленными онлайновыми API. Благодаря брокеру веб-аутентификации приложение может связывать пользователей с их онлайновыми персоналиями, контентом и сообществами, применяя OAuth или OpenID. WinJS и Windows Runtime дают вам все средства, упрощающие создание приложения, ценность которого превосходит суммарную ценность используемых им онлайновых сервисов.