<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Блог для разработчиков приложений для Windows 8</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/windowsappdev_ru/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/feed.xml</link>
    <description>Подробности создания Metro-приложений для Windows 8 от группы разработчиков Windows 8</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:28:54 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Все об обещаниях (для приложений Магазина Windows, написанных на JavaScript)</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/105</link>
      <pubDate>Wed, 26 Jun 2013 15:56:11 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/06/26/105/</guid>
      <description><![CDATA[При написании приложений Магазина Windows на языке JavaScript, как только вы захотите создать...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>При написании приложений Магазина Windows на языке JavaScript, как только вы захотите создать что-либо, связанное с асинхронным API, вы столкнетесь с конструкциями, называемыми <i><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/Hh700339.aspx">обещаниями</a> </i>(объектами отложенного результата). Пройдет немного времени, и написание цепочек обещаний для последовательных асинхронных операций станет для вас привычным делом.</p>  <p>При разработке приложений вам наверняка повстречаются и другие, не совсем очевидные способы использования обещаний. Хорошим примером этого является оптимизация функций отрисовки элементов для элемента управления ListView, представленная в <a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0">примере оптимизации производительности HTML ListView</a>. Мы рассмотрим эту тему подробнее в следующей статье. Или ознакомьтесь с крайне интересными сведениями, представленными Джошем Вильямсом (Josh Williams) в выступлении <a href="https://channel9.msdn.com/Events/Build/2012/4-101">Подробный обзор WinJS</a> на конференции //build 2012 (материал немного изменен):</p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">list.reduce(<span style="color: rgb(0, 0, 255);">function</span> callback (prev, item, i) {<br />    <span style="color: rgb(0, 0, 255);">var</span> result = doOperationAsync(item);<br />    <span style="color: rgb(0, 0, 255);">return</span> WinJS.Promise.join({ prev: prev, result: result}).then(<span style="color: rgb(0, 0, 255);">function</span> (v) {<br />        console.log(i + <span style="color: rgb(0, 96, 128);">&quot;, item: &quot;</span> + item+ <span style="color: rgb(0, 96, 128);">&quot;, &quot;</span> + v.result);<br />    });<br />})<br /></pre>
  </div>
</blockquote>

<p>Этот фрагмент кода объединяет обещания для параллельных асинхронных операций и выдает результаты последовательно в соответствии с их порядком в <i>списке</i>. Если, глядя на этот код, вы можете сразу же описать его назначение, можете пропустить данную статью. Если нет, давайте подробнее рассмотрим работу обещаний и их выражение в WinJS — библиотеке Windows для JavaScript, чтобы понимать схему их действия.</p>

<h2>Что собой представляет обещание? Отношения в случае обещания</h2>

<p>Давайте начнем с основополагающего факта: обещание — это просто конструкция кода или, если желаете, соглашение о вызовах. Таким образом, обещания не имеют обязательной связи с асинхронными операциями — просто их крайне <i>удобно </i>использовать в этом отношении. Обещание — это просто объект, представляющий значение, которое может быть доступно в некоторый момент в будущем либо прямо сейчас. Получается, что сущность обещания соответствует смыслу данного термина, когда он употребляется для описания отношений между людьми. Если я говорю: "Я обещаю принести вам десять бубликов", — это не значит, что эти бублики есть у меня прямо сейчас, однако я определенно подразумеваю, что я <i>получу </i>их в некоторый момент в будущем. И когда это произойдет, я их принесу.</p>

<p>Таким образом, обещание подразумевает отношение между двумя агентами: <i>инициатором</i>, который обещает предоставление некоторых товаров, и <i>потребителем</i>, который является получателем как такого обещания, так и непосредственно товаров. Как именно инициатор собирается получить товары, это его личное дело. Аналогичным образом, потребитель может делать все, что угодно, как с обещанием, так и с доставленными товарами. Он даже может использовать обещание совместно с другими потребителями.</p>

<p>Между инициатором и потребителем лежит два этапа этого отношения — <i>создание</i> и <i>исполнение</i>. Все это приведено на следующей схеме.</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0844.promise_diagram_577C7B9B.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0844.promise_5F00_diagram_5F00_577C7B9B.png"><img title="схема_обещания" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="схема_обещания" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0458.promise_diagram_thumb_0FBAF2B4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0458.promise_5F00_diagram_5F00_thumb_5F00_0FBAF2B4.png" width="700" height="341" /></a></p>

<p>Именно благодаря наличию двух этапов этого отношения, обещания отлично подходят для асинхронной доставки, как видно из приведенного на схеме потока. Основная идея заключается в том, что после получения подтверждения запроса, то есть обещания, потребитель может продолжать работу (асинхронный режим) вместо простого ожидания (синхронный режим). Это значит, что во время ожидания исполнения обещания потребитель может выполнять другие операции, например отвечать на другие запросы, в чем и заключается основная задача асинхронных API. А что если товары уже доступны? Тогда обещание исполняется моментально, как в случае соглашения о синхронных вызовах.</p>

<p>Конечно, это отношение имеет и другие особенности, которые нам следует учитывать. В своей жизни вы наверняка давали и принимали обещания. Хотя многие из них были выполнены, в реальности многие обещания нарушаются, например по пути к вам домой курьер из магазина может попасть аварию. Нарушенные обещания являются неотъемлемой частью жизни, поэтому нам следует принять это как должное и в личной жизни, и в асинхронном программировании.</p>

<p>С точки зрения отношений с использованием обещаний это значит, что инициатор должен иметь возможность сказать: "К сожалению, я не могу доставить товары по этому обещанию", — а потребитель должен иметь возможность узнать об этом. Во-вторых, когда мы выступаем в роли потребителя, то можем быть весьма нетерпеливыми, дожидаясь выполнения полученных обещаний. Поэтому, если инициатор может отслеживать ход выполнения своего обещания, потребителю также нужен способ для получения такой информации. В-третьих, потребитель также может отменить заказ и сообщить инициатору, что товары ему больше не требуются.</p>

<p>Добавив эти требования в схему, мы получаем полноценное отношение:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/4251.promise_diagram_2_23D40F3D.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/4251.promise_5F00_diagram_5F00_2_5F00_23D40F3D.png"><img title="promise_diagram_2" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="promise_diagram_2" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0550.promise_diagram_2_thumb_1CB4D2C5.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0550.promise_5F00_diagram_5F00_2_5F00_thumb_5F00_1CB4D2C5.png" width="700" height="432" /></a></p>

<p>Теперь давайте рассмотрим, как эти отношения проявляются в коде.</p>

<h2>Конструкция обещания и цепочки обещаний</h2>

<p>Для обещаний доступно множество разных предложений или спецификаций. Одним из них, используемым в Windows и WinJS, является <a href="http://wiki.commonjs.org/wiki/Promises/A">Common JS/Promises A</a>, где обещание описывается как нечто, возвращаемое инициатором для представления значения, предоставляемого в будущем, и является объектом с функцией <b>then</b>. Потребители подписываются на выполнение обещания, вызывая метод <b>then</b>. (В Windows обещания также поддерживают аналогичную функцию <b>done</b>, используемую, как мы скоро увидим, в цепочках обещаний.)</p>

<p>В эту функцию в качестве аргументов потребитель передает до трех дополнительных функций в следующем порядке:</p>

<ol>
  <li><i>Обработчик выполнения</i>. Инициатор вызывает эту функцию, когда обещанное значение доступно, и если оно доступно <i>прямо сейчас</i>, обработчик выполнения сразу (синхронно) вызывается из метода <b>then</b>.</li>

  <li>Дополнительный <i>обработчик ошибок</i>, вызываемый в случае сбоя при получении обещанного значения. Если для любого отдельного обещания был вызван обработчик ошибок, обработчик выполнения для него не вызывается никогда.</li>

  <li>Дополнительный <i>обработчик хода выполнения</i>, который периодически вызывается с промежуточными результатами, если это поддерживает выполняемая операция. (В WinRT это означает, что API имеет возвращаемое значение <b>IAsync[Action | Operation]WithProgress</b>, а интерфейсы с <b>IAsync[Action | Operation]</b> — нет.)</li>
</ol>

<p>Обратите внимание на то, что для любого из этих аргументов можно передать значение <i>null</i>, например, если вы хотите назначить только обработчик ошибок без обработчика выполнения. </p>

<p>Потребитель, находящийся на другой стороне отношения, может подписаться на любое число обработчиков для одного обещания, вызывая <b>then</b> несколько раз. Он также может использовать обещание совместно с другими потребителями, которые также имеют возможность вызывать метод <b>then</b> любое число раз. Все это полностью поддерживается.</p>

<p>Это значит, что обещание должно управлять списками всех получаемых обработчиков и вызывать их в нужное время. Кроме того, обещания должны допускать отмену, как указано на полной схеме отношения.</p>

<p>Другое требование, следующее из спецификации <i>Promises A</i>, заключается в возвращении обещания самим методом <b>then</b>. Такое второе обещание выполняется, когда возвращает данные обработчик выполнения, назначенный первой функции <b>promise.then</b>, и это возвращаемое значение доставляется в качестве результата второго обещания. Рассмотрите следующий фрагмент кода:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> promise1 = someOperationAsync();<br /><span style="color: rgb(0, 0, 255);">var</span> promise2 = promise1.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler1 (result1) { <span style="color: rgb(0, 0, 255);">return</span> 7103; } );<br />promise2.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler2 (result2) { });<br /></pre>
  </div>
</blockquote>

<p>Здесь цепочка выполнения начинается с запуска <b>someOperationAsync</b>, возвращающего <i>promise1</i>. Во время выполнения этой операции мы вызываем функцию <b>promise1.then</b>, которая немедленно возвращает <i>promise2</i>. Следует понимать, что <b>completedHandler1</b> вызывается только в тех случаях, когда результат асинхронной операции уже доступен. Предположим, что мы все еще ждем, поэтому выполняем вызов <b>promise2.then</b>, и снова completedHandler2 при этом <i>не </i>вызывается.</p>

<p>Немного позднее <b>someOperationAsync</b> завершается со значением, например 14618. Обещание <i>promise1 </i>теперь выполнено, поэтому оно вызывает <b>completedHandler1</b> с этим значением, и результат <i>result1</i> будет равен 14618. Теперь выполняется <b>completedHandler1</b>, возвращая значение 7103. При этом выполняется обещание <i>promise2</i>, поэтому оно вызывает <b>completedHandler2</b> с результатом <i>result2</i>, равным 7103.</p>

<p>А что если обработчик выполнения возвращает еще одно обещание? Этот случай обрабатывается немного иначе. Предположим, что <b>completedHandler1</b> из предыдущего кода возвращает следующее обещание:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> promise2 = promise1.then(<span style="color: rgb(0, 0, 255);">function</span> completedHandler1 (result1) {<br />    <span style="color: rgb(0, 0, 255);">var</span> promise2a = anotherOperationAsync();<br />    <span style="color: rgb(0, 0, 255);">return</span> promise2a;<br />});<br /></pre>
  </div>
</blockquote>

<p>В этом случае <i>result2 </i>в <b>completedHandler2 </b>будет не самим <i>promise2a</i>, а значением <u>fulfillment</u> для <i>promise2a</i>. Таким образом, поскольку обработчик выполнения возвращает обещание, <i>promise2</i>, как возвращенное из <b>promise1.then</b>, будет выполнено с результатами <i>promise2a</i>.</p>

<p>Именно это делает возможным объединение последовательных асинхронных операций в цепочки, где результаты каждой операции цепочки передаются в следующую операцию. Без промежуточных переменных или именованных обработчиков цепочки обещаний часто имеют следующую структуру:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">operation1().then(<span style="color: rgb(0, 0, 255);">function</span> (result1) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation2(result1)<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result2) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation3(result2);<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result3) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation4(result3);<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result4) {<br />    <span style="color: rgb(0, 0, 255);">return</span> operation5(result4)<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (result5) {<br />    <span style="color: rgb(0, 128, 0);">//And so on</span><br />});<br /></pre>
  </div>
</blockquote>

<p>Конечно, с большой долей вероятности каждый обработчик выполнения выполняет с получаемыми результатами дополнительные действия, однако данная базовая структура присутствует во всех цепочках. Кроме того, здесь все методы <b>then</b> выполняются один за другим, поскольку они только сохраняют заданный обработчик выполнения и возвращают еще одно обещание. Таким образом, когда мы добрались до конца кода, была запущена только <i>operation1</i> и не были вызваны никакие обработчики выполнения. Однако был создан набор связанных между собой промежуточных обещаний из всех вызовов <b>then</b>, чтобы цепочкой можно было управлять как ходом выполнения последовательных операций.</p>

<p>Следует отметить, что аналогичную последовательность можно получить, вкладывая каждую последующую операцию в предыдущий обработчик выполнения; в этом случае у вас не будет всех операторов <i>return</i>. Однако такие вложения становятся кошмаром при структурировании кода с использованием отступов, особенно если вы начинаете добавлять обработчики хода выполнения и ошибок вместе с каждым вызовом <b>then</b>.</p>

<p>Кстати, одна из возможностей обещаний в WinJS заключается в том, что ошибки, возникающие в любой части цепочки, автоматически распространяются до ее конца. Это означает, что вместо использования обработчиков ошибок на каждом уровне, вы можете просто прикрепить отдельный обработчик ошибок к последнему вызову <b>then</b>. Здесь однако следует предупредить, что по различным причинам такие ошибки поглощаются в случае, если последним звеном цепочки является вызов <b>then</b>. Именно поэтому WinJS предоставляет для обещаний еще и метод <b>done</b>. Он принимает те же аргументы, что и метод <b>then</b>, однако указывает, что цепочка завершена (возвращает <i>undefined</i> вместо очередного обещания). Любой обработчик ошибок, прикрепленный к методу <b>done</b>, вызывается для всех ошибок во всей цепочке. Кроме того, если метод <b>done</b> не имеет обработчик ошибок, он выдает исключение на уровне приложений, где оно может быть обработано <b>window.onerror</b> событий <b>WinJS.Application.onerror</b>. Одним словом, в идеальном случае все цепочки должны заканчиваться методом <b>done</b>, чтобы обеспечить предоставление и правильную обработку исключений.</p>

<p>Конечно, если вы создаете функцию, <i>предназначенную</i> для возврата последнего обещания из длинной цепочки вызовов <b>then</b>, то все равно используете в конце <b>then</b>: в этом случае ответственность за обработку ошибок несет вызывающий объект, который может параллельно использовать это обещание в другой цепочке.</p>

<h2>Создание обещаний: класс WinJS.Promise</h2>

<p>Хотя вы всегда можете создать собственные классы обещаний на базе спецификации <i>Promises A</i>, это требует значительных усилий, которые можно сэкономить, используя библиотеку. Поэтому WinJS предоставляет надежный, протестированный и гибкий класс обещаний <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211867.aspx"><b>WinJS.Promise</b></a>. Он позволяет легко создавать обещания для разных значений и операций, не вникая в тонкости управления отношениями инициатора и потребителя или работы функции <b>then</b>.</p>

<p>Когда потребуется, вы можете (и должны) использовать <b>новый класс WinJS.Promise</b> (либо подходящую вспомогательную функцию, как указано в следующем разделе) в целях создания обещаний как для асинхронных операций, так и для существующих (синхронных) значений. Помните о том, что обещание — это просто конструкция кода: нет никакого требования, предписывающего, чтобы обещание охватывало асинхронную операцию или <i>что бы то ни было</i> асинхронное. Аналогичным образом, сам факт заключения фрагмента кода в обещание еще не <i>гарантирует </i>асинхронности его выполнения<i>. </i>Эту работу вам придется сделать самостоятельно.</p>

<p>В качестве простого примера прямого использования класса <b>WinJS.Promise</b> давайте предположим, что требуется выполнить длинное вычисление — простое суммирование набора значений от единицы до некоторого максимума, делая это в асинхронном режиме. Мы могли бы разработать для такой подпрограммы свой механизм обратного вызова, но если мы заключим ее в обещание, мы обеспечим возможность связывания в цепочку или соединения с другими обещаниями из других API. (По этому принципу функция <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229787.aspx"><b>WinJS.xhr</b></a> заключает асинхронный запрос <b>XmlHttpRequest</b> JavaScript в обещание, чтобы вам не пришлось разбираться в структуре событий такого запроса.)</p>

<p>Разумеется, мы можем использовать для длинного вычисления рабочий процесс JavaScript, но, чтобы проиллюстрировать этот пример, мы продолжим работать в потоке пользовательского интерфейса и воспользуемся <b>setImmediate</b> для разделения этой операции на этапы. Вот как это можно реализовать в структуре обещаний, используя <b>WinJS.Promise</b>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> calculateIntegerSum(max, step) {<br />    <span style="color: rgb(0, 128, 0);">//The WinJS.Promise constructor's argument is an initializer function that receives </span><br />    <span style="color: rgb(0, 128, 0);">//dispatchers for completed, error, and progress cases.</span><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />        <span style="color: rgb(0, 0, 255);">var</span> sum = 0;<br /><br />        <span style="color: rgb(0, 0, 255);">function</span> iterate(args) {<br />            <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = args.start; i &lt; args.end; i++) {<br />                sum += i;<br />            };<br /><br />            <span style="color: rgb(0, 0, 255);">if</span> (i &gt;= max) {<br />                <span style="color: rgb(0, 128, 0);">//Complete--dispatch results to completed handlers</span><br />                completeDispatch(sum);<br />            } <span style="color: rgb(0, 0, 255);">else</span> {<br />                <span style="color: rgb(0, 128, 0);">//Dispatch intermediate results to progress handlers</span><br />                progressDispatch(sum);<br />                setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });<br />            }<br />        }<br />            <br />        setImmediate(iterate, { start: 0, end: Math.min(step, max) });<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>При вызове <b>нового класса WinJS.Promise</b> единственным аргументом для его конструктора является функция <i>initializer</i> (в данном случае анонимная). Функция initializer инкапсулирует выполняемую операцию, однако очевидно, что сама эта функция в потоке пользовательского интерфейса выполняется <i>синхронно</i>. Если бы сейчас мы выполнили длинное вычисление, не используя <b>setImmediate,</b> то заблокировали бы поток пользовательского интерфейса на все время вычисления. Еще раз отметим — помещение кода внутрь обещания еще не делает этот код<i> </i>асинхронным, это необходимо настроить в функции initializer.</p>

<p>В качестве аргументов функция initializer принимает три <i>диспетчера</i> для случаев выполнения, ошибки и хода выполнения, которые поддерживаются этими обещаниями. Как видите, мы вызываем эти диспетчеры в нужные моменты во время операции с использованием подходящих аргументов.</p>

<p>Я называю эти функции "диспетчерами", поскольку они отличаются от обработчиков, которые потребители подписывают на метод <b>then</b> обещания (или метод <b>done</b>, но я больше не буду напоминать об этом). Если разобраться, WinJS управляет массивами этих обработчиков, что позволяет любому числу потребителей подписаться на любое число обработчиков. Когда вы вызываете один из таких диспетчеров, WinJS выполняет итерации по своему внутреннему списку и вызывает все эти обработчики от вашего имени. Кроме того, <b>WinJS.Promise</b> проверяет, что метод <b>then</b> возвращает другое обещание, что необходимо для образования цепочки.</p>

<p>По сути, <b>WinJS.Promise</b> предоставляет все детали, окружающие и дополняющие обещание. Благодаря этому вы можете сконцентрироваться на основной операции обещания, которая помещается в функцию initializer.</p>

<h2>Вспомогательные средства для создания обещаний</h2>

<p>Основной вспомогательной функцией для создания обещания является статический метод <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211664.aspx"><b>WinJS.Promise.as</b></a>, охватывающий <i>любое</i> значение в обещании Применение такой оболочки для уже существующего значения не привносит ничего нового и вызывает любой обработчик выполнения, переданный в <b>then</b>. Это позволяет обрабатывать произвольные известные значения как обещания, чтобы вы могли смешивать и сопрягать их с другими обещаниями (посредством присоединения или объединения в цепочку). Использование <b>as</b> для существующего обещания просто возвращает само это обещание.</p>

<p>Другой статической вспомогательной функцией является <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229729.aspx"><b>WinJS.Promise.timeout</b></a>, которая предоставляет удобную оболочку для <b>setTimeout</b> и <b>setImmediate</b>. Вы также можете создать обещание, которое отменяет второе обещание, если это второе обещание не выполнено в течение заданного числа миллисекунд.</p>

<p>Обратите внимание, что обещания <b>timeout</b> для <b>setTimeout</b> и <b>setImmediate</b> сами исполняются с <i>undefined</i>. Часто спрашивают: "Как можно использовать их для предоставления других результатов после истечения времени ожидания?" В ответе используется тот факт, что функция <b>then</b> возвращает другое обещание, выполняемое с возвращаемым значением обработчика выполнения. Приведем в качестве примера следующую строку кода:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> p = WinJS.Promise.timeout(1000).then(<span style="color: rgb(0, 0, 255);">function</span> () { <span style="color: rgb(0, 0, 255);">return</span> 12345; });</pre>
  </div>
</blockquote>

<p>Она создает обещание <i>p</i>, которое будет выполнено со значением 12345 через одну секунду. Другими словами, <b>WinJS.Promise.timeout(…).then(function () { return &lt;значение>} )</b> является шаблоном для предоставления <i>&lt;значения></i> после истечения времени ожидания. А если само <i>&lt;значение></i> является другим обещанием, оно служит для предоставления значения выполнения из этого обещания в определенный момент после истечения времени ожидания.</p>

<h2>Ошибки при отмене и создании обещаний</h2>

<p>В предыдущем коде вы могли заметить два недостатка. Первый заключается в отсутствии способа отмены операции после ее начала. Второй — в неудовлетворительной обработке ошибок.</p>

<p>В обоих случаях особенность состоит в том, что функции создания обещаний, такие как <b>calculateIntegerSum</b>, должны всегда возвращать обещание. Если операция не может быть выполнена или никогда не запускается, такое обещание находится в <i>состоянии ошибки</i>. Это значит, что обещание не имеет и никогда не <i>будет</i> иметь результат, который оно сможет передать в любой из обработчиков выполнения: оно просто постоянно вызывает свои обработчики ошибок. В самом деле, если потребитель вызывает <b>then</b> для обещания, которое уже находится в состоянии ошибки, это обещание немедленно (синхронно) вызывает обработчик ошибок, назначенный <b>then</b>.</p>

<p><b>WinJS.Promise</b> переходит в состояние ошибки по двум причинам: потребитель вызывает свой метод <b>cancel</b>, либо код в функции initializer вызывает диспетчер ошибок. Когда такое происходит, обработчики ошибок получают значение ошибки, которое было перехвачено или распространено в обещании. Если вы создаете операцию в <b>WinJS.Promise</b>, то можете также использовать экземпляр <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211689.aspx"><b>WinJS.ErrorFromName</b></a>. Это просто объект JavaScript, содержащий свойство <i>name</i>, идентифицирующее ошибку, и свойство <i>message</i>, содержащее дополнительную информацию. Например, при отмене обещания обработчики ошибок получают объект ошибки, в котором как для <i>name</i>, так и для <i>message</i> установлено значение "Canceled".</p>

<p>Но что если вы не можете даже запустить операцию? Например, если вы вызываете функцию <b>calculateIntegerSum</b> с неправильными аргументами (например, 0, 0), она даже не должна пытаться начать считать, а должна возвратить обещание в состоянии ошибки. Именно для этого и служит статический метод <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229784.aspx"><b>WinJS.Promise.wrapError</b></a>. Он принимает экземпляр <b>WinJS.ErrorFromName</b> и возвращает обещание в состоянии ошибки, которое нам требуется в данном случае вместо нового экземпляра <b>WinJS.Promise</b>.</p>

<p>Другая особенность заключается в том, что хотя вызов метода <b>cancel</b> обещания переводит само обещание в состояние ошибки, возникает вопрос: как остановить асинхронную операцию, которая уже выполняется? В предыдущей реализации <b>calculateIntegerSum</b> она просто продолжала вызывать <b>setImmediate</b> до выполнения операции, независимо от состояния созданного нами обещания. Фактически, если операция вызывает диспетчер выполнения после отмены обещания, это обещание просто игнорирует такое завершение.</p>

<p>Поэтому необходим способ, с помощью которого обещание сможет сообщить операции, что ее выполнение больше не требуется. Для этого конструктор <b>WinJS.Promise</b> использует второй аргумент функции, вызываемый при отмене обещания. В нашем примере при вызове этой функции потребовалось бы предотвратить следующий вызов <b>setImmediate</b>, что привело бы к остановке вычисления. Вот как это выглядит с правильной обработкой ошибок:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> calculateIntegerSum(max, step) {<br />    <span style="color: rgb(0, 128, 0);">//Return a promise in the error state for bad arguments</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (max &lt; 1 || step &lt; 1) {<br />        <span style="color: rgb(0, 0, 255);">var</span> err = <span style="color: rgb(0, 0, 255);">new</span> WinJS.ErrorFromName(<span style="color: rgb(0, 96, 128);">&quot;calculateIntegerSum&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;max and step must be 1 or greater&quot;</span>);<br />        <span style="color: rgb(0, 0, 255);">return</span> WinJS.Promise.wrapError(err);<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">var</span> _cancel = <span style="color: rgb(0, 0, 255);">false</span>;<br /><br />    <span style="color: rgb(0, 128, 0);">//The WinJS.Promise constructor's argument is an initializer function that receives </span><br />    <span style="color: rgb(0, 128, 0);">//dispatchers for completed, error, and progress cases.</span><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />        <span style="color: rgb(0, 0, 255);">var</span> sum = 0;<br /><br />        <span style="color: rgb(0, 0, 255);">function</span> iterate(args) {<br />            <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = args.start; i &lt; args.end; i++) {<br />                sum += i;<br />            };<br /><br />            <span style="color: rgb(0, 128, 0);">//If for some reason there was an error, create the error with WinJS.ErrorFromName</span><br />            <span style="color: rgb(0, 128, 0);">//and pass to errorDispatch</span><br />            <span style="color: rgb(0, 0, 255);">if</span> (<span style="color: rgb(0, 0, 255);">false</span> <span style="color: rgb(0, 128, 0);">/* replace with any necessary error check -- we don’t have any here */</span>) {<br />                errorDispatch(<span style="color: rgb(0, 0, 255);">new</span> WinJS.ErrorFromName(<span style="color: rgb(0, 96, 128);">&quot;calculateIntegerSum (scenario 7)&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;error occurred&quot;</span>));<br />            }<br /><br />            <span style="color: rgb(0, 0, 255);">if</span> (i &gt;= max) {<br />                <span style="color: rgb(0, 128, 0);">//Complete--dispatch results to completed handlers</span><br />                completeDispatch(sum); <br />            } <span style="color: rgb(0, 0, 255);">else</span> {<br />                <span style="color: rgb(0, 128, 0);">//Dispatch intermediate results to progress handlers</span><br />                progressDispatch(sum);<br /><br />                <span style="color: rgb(0, 128, 0);">//Interrupt the operation if canceled</span><br />                <span style="color: rgb(0, 0, 255);">if</span> (!_cancel) {<br />                    setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });<br />                }<br />            }<br />        }<br />            <br />        setImmediate(iterate, { start: 0, end: Math.min(step, max) });<br />    },<br />    <span style="color: rgb(0, 128, 0);">//Cancellation function for the WinJS.Promise constructor</span><br />    <span style="color: rgb(0, 0, 255);">function</span> () {<br />        _cancel = <span style="color: rgb(0, 0, 255);">true</span>;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>В целом создание экземпляров <b>WinJS.Promise</b> имеет множество применений. Например, если у вас есть библиотека, взаимодействующая с веб-службой посредством другого асинхронного метода, вы можете заключить эти операции в обещания. Вы также можете использовать новое обещание для объединения нескольких асинхронных операций (или других обещаний) из разных источников в одно обещание в тех случаях, когда требуется управлять всеми доступными отношениями. В коде функции initializer для <b>WinJS.Promise</b> вы, несомненно, можете использовать собственные обработчики для остальных асинхронных операций и их обещаний. Их можно использовать, чтобы инкапсулировать механизмы автоматического выполнения повторных попыток для времени недоступности сети и т. п., подключения к универсальному пользовательскому интерфейсу обновления хода выполнения или добавления встроенных функций ведения журналов или аналитики. Во всех этих случаях не нужно сообщать отдельные подробности в остальной код, и он может просто работать с обещаниями со стороны потребителей.</p>

<p>Таким образом довольно просто заключить рабочий процесс JavaScript в обещание, чтобы он выглядел и работал как другие асинхронные операции в WinRT. Возможно, вы уже знаете, что рабочие процессы предоставляют свои результаты посредством вызова <b>postMessage</b>, вызывающего событие <b>message</b> для объекта рабочего процесса в приложении. Следующий код связывает это событие с обещанием, которое выполняется при доставке любых результатов в этом сообщении:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// This is the function variable we're wiring up.</span><br /><span style="color: rgb(0, 0, 255);">var</span> workerCompleteDispatch = <span style="color: rgb(0, 0, 255);">null</span>;<br /><br /><span style="color: rgb(0, 0, 255);">var</span> promiseJS = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (completeDispatch, errorDispatch, progressDispatch) {<br />    workerCompleteDispatch = completeDispatch;<br />});<br /><br /><span style="color: rgb(0, 128, 0);">// Worker is created here and stored in the 'worker' variable</span><br /><br /><span style="color: rgb(0, 128, 0);">// Listen for worker events</span><br />worker.onmessage = <span style="color: rgb(0, 0, 255);">function</span> (e) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (workerCompleteDispatch != <span style="color: rgb(0, 0, 255);">null</span>) {<br />        workerCompleteDispatch(e.data.results); <span style="color: rgb(0, 128, 0);">/* event args depends on the worker */</span><br />    }<br />}<br /><br />promiseJS.done(<span style="color: rgb(0, 0, 255);">function</span> (result) {<br />    <span style="color: rgb(0, 128, 0);">// Output for JS worker</span><br />});<br /></pre>
  </div>
</blockquote>

<p>Чтобы дополнить этот код для обработки ошибок из рабочего процесса, сохраните диспетчер ошибок в другой переменной, сделайте так, чтобы обработчик событий <b>message</b> проверил наличие информации об ошибке в своих аргументах событий, а также при необходимости вызовите диспетчер ошибок вместо диспетчера выполнения.</p>

<h2>Объединение параллельных обещаний</h2>

<p>Поскольку обещания часто используются для представления асинхронных операций, вы определенно можете обеспечить параллельное выполнение нескольких операций. В этих случаях вам может потребоваться узнать, когда выполняется одно из обещаний в группе либо выполняются все обещания в группе. Для этого служат статические функции <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229660.aspx"><b>WinJS.Promise.any</b></a> и <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211774.aspx"><b>WinJS.Promise.join</b></a>.</p>

<p>Обе функции принимают массив значений или объект со свойствами значений. Эти значения могут быть обещаниями, а все отличные от обещаний значения описываются с помощью <b>WinJS.Promise.as</b>, в результате весь массив или объект состоит из обещаний.</p>

<p>Ниже представлены характеристики функции <b>any</b>:</p>

<ul>
  <li>Функция <b>any</b> создает отдельное обещание, которое выполняется, когда выполняется или завершается с ошибкой одно из других обещаний (логическое ИЛИ). Фактически, функция <b>any</b><i> </i>подключает обработчики выполнения ко всем этим обещаниям, и как только вызывается один из обработчиков выполнения, она вызывает все обработчики выполнения, принятые обещанием <b>any</b><i></i>.</li>

  <li>После выполнения обещания <b>any</b><i> </i>(то есть после выполнения первого обещания в списке) остальные операции в списке продолжают выполняться, вызывая все обработчики выполнения, ошибок или хода выполнения, назначенные таким обещаниям в индивидуальном порядке.</li>

  <li>Если вы отменяете обещание из <b>any</b>, отменяются все обещания в этом списке.</li>
</ul>

<p>Характеристики функции <b>join</b>:</p>

<ul>
  <li>Функция <b>join</b> создает отдельное обещание, которое выполняется, когда выполняются или завершаются с ошибкой <i>все</i> другие обещания (логическое И). Фактически функция <b>join</b><i> </i>подключает обработчики выполнения и ошибок ко всем этим обещаниям и ожидает вызова всех этих обработчиков, прежде чем вызывает все обработчики выполнения, получаемые ей самой.</li>

  <li>Обещание <b>join</b> также сообщает о ходе выполнения в любые предоставленные вами обработчики хода выполнения. Промежуточным результатом в этом случае является массив результатов из отдельных обещаний, выполненных на данный момент.</li>

  <li>Если вы отменяете обещание из <b>join</b>, отменяются все остальные ожидающие обещания.</li>
</ul>

<p>Кроме <b>any</b> и <b>join</b>, имеется еще два статических метода <b>WinJS.Promise</b>, о которых следует знать, так как они могут оказаться полезными:</p>

<ul>
  <li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211765.aspx"><b>is</b></a> определяет, является ли произвольное значение обещанием, возвращая логическое значение. Если не вдаваться в подробности, он просто проверяет, что это объект с функцией "then"; наличие функции "done" он не проверяет.</li>

  <li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229727.aspx"><b>theneach</b></a><i> </i>применяет обработчики выполнения, ошибок и хода выполнения к группе обещаний (с использованием <b>then</b>), при этом возвращает результаты в виде другой группы значений внутри обещания. Любой из этих обработчиков может иметь значение <i>null</i>.</li>
</ul>

<h2>Параллельные обещания с последовательными результатами</h2>

<p>Благодаря <b>WinJS.Promise.join</b>и <b>WinJS.Promise.any</b> мы получаем возможность работать с параллельными обещаниями, то есть с параллельными асинхронными операциями. Еще раз отмечу, что обещание, возвращаемое функцией <b>join</b>, выполняется, когда выполнены все обещания в массиве. Однако такие обещания обычно выполняются в случайном порядке. А что если бы у вас был набор операций, выполняющихся подобным образом, но вам бы хотелось обрабатывать их результаты строго упорядоченным образом, а именно в порядке следования обещаний в массиве?</p>

<p>Для этого вам необходимо присоединить каждое последующее обещание к функции <b>join</b> из всех предыдущих. А ведь код, с которого мы начали настоящую статью, выполняет именно такую задачу. Еще раз приведем этот код, но переписанный таким образом, чтобы сделать обещания явными. (Предположим, что <i>list</i><b> </b>— это массив значений определенного рода, использующихся в качестве аргументов для гипотетического асинхронного вызова с созданием обещаний <b>doOperationAsync</b>):</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">list.reduce(<span style="color: rgb(0, 0, 255);">function</span> callback (prev, item, i) {<br />    <span style="color: rgb(0, 0, 255);">var</span> opPromise = doOperationAsync(item);<br />    <span style="color: rgb(0, 0, 255);">var</span> join = WinJS.Promise.join({ prev: prev, result: opPromise});<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> join.then(<span style="color: rgb(0, 0, 255);">function</span> completed (v) {<br />        console.log(i + <span style="color: rgb(0, 96, 128);">&quot;, item: &quot;</span> + item+ <span style="color: rgb(0, 96, 128);">&quot;, &quot;</span> + v.result);<br />    });<br />})<br /></pre>
  </div>
</blockquote>

<p>Чтобы понять этот код, нам сначала нужно разобраться, как работает метод <a href="http://msdn.microsoft.com/ru-ru/library/ie/ff679975(v=vs.94).aspx"><b>reduce</b></a> этого массива. Для каждого элемента в массиве <b>reduce</b> вызывает аргумент функции, который здесь назван <b>callback</b> и принимает четыре аргумента (из которых только три используются в коде):</p>

<ul>
  <li><i>prev</i> — значение, возвращенное из <i>предыдущего</i> вызова <b>callback</b> (для первого элемента оно равно <i>null</i>).</li>

  <li><i>item</i> — текущее значение из массива.</li>

  <li><i>i</i> — индекс элемента в списке.</li>

  <li><i>source</i> — исходный массив.</li>
</ul>

<p>Для первого элемента в списке мы получаем обещание, которое назову <b>opPromise<sub>1</sub></b>. Поскольку <b>prev</b> равно <i>null</i>, мы присоединяем <b>[WinJS.Promise.as(null), opPromise<sub>1</sub>]</b>. Однако обратите внимание на то, что мы не возвращаем саму функцию <b>join</b>. Вместо этого мы подключаем к этому объединению обработчик выполнения (который я назвал <b>completed</b>) и возвращаем обещание из его <b>then</b>.</p>

<p>Помните, что обещание, возвращенное из <b>then</b>, будет выполнено при возвращении обработчика выполнения. Это значит, что данные, возвращаемые из <b>callback</b>, являются обещанием, которое не исполняется до тех пор, пока обработчик <b>completed</b> первого элемента не обработает результаты из <b>opPromise<sub>1</sub></b>. И если вы посмотрите на результат объединения, оно выполняется с объектом, содержащим результаты из обещаний в исходном списке. Это значит, что значение выполнения <i>v</i> будет содержать как свойство <i>prev</i>, так и свойство <i>result</i>, при этом второе является результатом обещания <b>opPromise<sub>1</sub></b>.</p>

<p>Вместе со следующим элементом в <i>list</i> <b>callback</b> получает свойство <i>prev</i>, содержащее обещание из предыдущего <b>join.then</b>. После этого мы создаем новое объединение <b>opPromise<sub>1</sub>.then</b> и <b>opPromise<sub>2</sub></b>. В результате такое присоединение не выполняется, пока не будет выполнено обещание <b>opPromise<sub>2</sub></b> <i>и</i> обработчик выполнения для <b>opPromise<sub>1</sub></b> не возвратит значение. Вуаля! Обработчик <b>completed<sub>2</sub></b>, который мы подключаем к этому <b>join</b>, не вызывается до тех пор, пока не будет возвращен <b>completed<sub>1</sub></b>.</p>

<p>Аналогичные зависимости продолжают создаваться для каждого элемента в списке — обещание из <b>join.then</b> для элемента <i>n </i>не выполняется, пока не будет возвращен <b>completed<i><sub>n</sub></i></b>. Таким образом гарантируется вызов обработчиков выполнения в том же порядке, что и в <i>list</i>.</p>

<h2>Заключение</h2>

<p>В этой статье мы показали, что сами по себе обещания — это просто конструкция кода или соглашение о вызовах, которые можно эффективно использовать. Обещания используются для представления определенного отношения между инициатором, располагающим значениями, которые требуется предоставить в произвольное время в будущем, и потребителем, которому требуется знать, когда эти значения будут доступны. Таким образом, обещания отлично подходят для представления результатов из асинхронных операций и широко используются в приложениях Магазина Windows, написанных на JavaScript. Спецификация для обещаний также допускает объединение последовательных асинхронных операций в цепочки, где каждый промежуточный результат переходит от одного звена к другому.</p>

<p>Библиотека Windows для JavaScript (WinJS) предоставляет надежную реализацию обещаний, которую вы можете использовать для описания своих операций любого вида. Она также предоставляет вспомогательные средства для распространенных сценариев, таких как объединение обещаний для реализации параллельных операций. Благодаря этому WinJS делает работу с асинхронными операциями более удобной и эффективной.</p>

<p>Крэйг Брокшмидт (Kraig Brockschmidt) 
  <br />Руководитель программы, рабочая группа по экосистеме Windows 

  <br />Автор книги <a href="http://blogs.msdn.com/b/microsoft_press/archive/2012/10/29/free-ebook-programming-windows-8-apps-with-html-css-and-javascript.aspx"><i>Programming Windows 8 Apps in HTML, CSS, and JavaScript (Программирование приложений для Windows 8 на HTML, CSS и JavaScript)</i></a></p>

<!-- Title: “Все об обещаниях (для приложений Магазина Windows, написанных на JavaScript)” Tags: “JavaScript, приложения Магазина Windows, обещания” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Оптимизация отрисовки элементов ListView</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/33</link>
      <pubDate>Tue, 25 Jun 2013 14:40:33 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/06/25/33/</guid>
      <description><![CDATA[Для многих приложений Магазина Windows, написанных на JavaScript и работающих с коллекциями,...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Для многих <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211385.aspx" target="_blank">приложений Магазина Windows, написанных на JavaScript</a> и работающих с коллекциями, хорошее взаимодействие <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211837.aspx" target="_blank">с элементом управления WinJS ListView</a> просто необходимо для оптимизации производительности. И это неудивительно: когда вы занимаетесь отображением тысяч элементов и их управлением, ценится любое усилие по их оптимизации. Самое важное — как каждый из этих элементов отрисовывается, т.е. как и когда каждый элемент из ListView формируется в DOM и становится видимой частью приложения. <i>Время</i> (компонент "когда") в этом уравнении становится критически важным фактором, если пользователь быстро перемещается по списку и ожидает, что список будет "успевать" за его перемещениями.</p>  <p>Отрисовка элементов в ListView осуществляется с помощью декларативного шаблона, определенного в HTML, или настраиваемой <i>функции отрисовки</i> JavaScript, вызываемой для каждого элемента в списке. Хотя использование декларативного шаблона — самый простой путь, он не обеспечивает достаточно широких возможностей управления этим процессом. Функция отрисовки наоборот позволяет поэлементно настроить отрисовку и оптимизировать процесс, как показано в <a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0" target="_blank">примере оптимизации производительности HTML ListView</a>. Используются следующие возможности оптимизации:</p>  <ul>   <li>Асинхронная доставка данных элемента и отображаемого элемента с поддержкой базовых функций отрисовки.</li>    <li>Раздельное создание формы элементы, необходимой для общей разметки ListView, и его внутренних компонентов. Это поддерживается с помощью средства отрисовки заполнителя.</li>    <li>Повторное использование ранее созданного элемента (и дочерних элементов) с заменой данных, что позволяет пропустить большинство действий по созданию элемента. Предоставляется с помощью средства отрисовки заполнителя с повторным использованием.</li>    <li>Задержка выполнения ресурсоемких визуальных операций, таких как загрузка изображений и анимация, до отображения элемента (если для ListView не используется быстрое панорамирование) с помощью средства многоэтапной отрисовки.</li>    <li>Пакетное выполнение одинаковых визуальных операций, чтобы свести к минимуму повторную отрисовку DOM, с помощью средства многоэтапной пакетной отрисовки.</li> </ul>  <p>В этой записи блога мы рассмотрим все эти этапы и узнаем, как они взаимодействуют в процессе визуализации элемента ListView. Очевидно, что для оптимизации <i>времени</i> отрисовки элемента необходимо множество асинхронных операций, а значит и множество обещаний. Таким образом, в процессе изучения мы также лучше разберемся в том, что такое обещания, описанные в предыдущей записи этого блога <a href="http://blogs.msdn.com/b/windowsappdev/archive/2013/06/10/all-about-promises-for-windows-store-apps-written-in-javascript.aspx" target="_blank">Все об обещаниях</a>.</p>  <p>Для всех средств отрисовки всегда важно свести к минимуму базовое время отрисовки элемента (не учитывая отложенные операции). Поскольку конечная производительность ListView сильно зависит от того, насколько его обновления согласованы с интервалами обновления экрана, несколько лишних миллисекунд в отрисовке элемента могут значительно увеличить общее время визуализации ListView в течение следующего интервала обновления. Из-за этого могут пропадать кадры, а изображение будет казаться нестабильным. Другими словами, если вы хотите оптимизировать код JavaScript, делайте это в средствах отрисовки элементов.</p>  <h2>Базовые средства отрисовки</h2>  <p>Начнем с краткого обзора функции отрисовки элемента, которую я буду называть <i>средством отрисовки</i>. Средство отрисовки — это функция, которую вы назначаете свойству <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh700705.aspx" target="_blank">itemTemplate</a> элемента управления ListView вместо имени шаблона. Она при необходимости вызывается для элементов, которые ListView хочет включить в DOM. (Кстати, базовую документацию по средствам отрисовки можно найти на странице <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh700705.aspx" target="_blank">itemTemplate</a>. Но описанные возможности оптимизации демонстрируются именно в примере.)</p>  <p>Можно ожидать, что функция отрисовки просто получает элемент из источника данных ListView. Затем она создает необходимые HTML-элементы и возвращает корневой элемент, который ListView может добавить в DOM. В целом, именно эти и происходит, но стоит отметить два момента. Во-первых, сами данные элемента могут загружаться асинхронно, поэтому имеет смысл привязать создание элемента к доступности данных. Кроме того, в процесс отрисовки элемента могут входить другие асинхронные операции, например загрузка изображений из удаленных URI или чтение данных из других файлов, определенных в данных элемента. Как мы увидим, разные уровни оптимизации позволяют выполнять произвольный объем асинхронных операций между запросом компонентов элемента и их фактической доставкой.</p>  <p>Опять же, можно ожидать использования обещаний! ListView не просто напрямую передает данные элемента средству отрисовки, а предоставляет обещание об этих данных. А функция не возвращает корневой компонент элемента напрямую, а возвращает обещание об этом компоненте. Это позволяет ListView объединить множество обещаний отрисовки элемента и ждать (асинхронно) визуализации целой страницы. Так ListView будет интеллектуально управлять формированием разных страниц, сначала создавая страницу видимых элементов, а затем — предыдущую и следующую страницы, на которые вероятнее всего перейдут пользователи. Кроме того, наличие всех этих обещаний означает, что ListView может легко отменить отрисовку незаконченных элементов, если пользователь перейдет к другим элементам. Это позволит избежать создания ненужных элементов.</p>  <p>Использование таких обещаний можно увидеть в функции <b>simpleRenderer</b> в примере:</p>  <p> </p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> simpleRenderer(itemPromise) {<br />    <span style="color: rgb(0, 0, 255);">return</span> itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />        <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />        element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;img src='&quot;</span> + item.data.thumbnail +<br />            <span style="color: rgb(0, 96, 128);">&quot;' alt='Databound image' /&gt;&lt;div class='content'&gt;&quot;</span> + item.data.title + <span style="color: rgb(0, 96, 128);">&quot;&lt;/div&gt;&quot;</span>;<br />        <span style="color: rgb(0, 0, 255);">return</span> element;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Этот код сначала присоединяет обработчик выполнения к <b>itemPromise</b>. Этот обработчик вызывается, когда данные элемента доступны, и создает в ответ компоненты. Но снова обратите внимание, что мы не возвращаем компонент напрямую, а возвращаем обещание, которое будет выполнено с этим компонентом. Следовательно возвращаемое <b>itemPromise.then()</b> значение — это обещание, выполняемое с <i>компонентом</i>, когда и если он потребуется ListView.</p>

<p>Возвращая обещания, мы можем при необходимости выполнять другие асинхронные операции. В этом случае средство отрисовки может объединять промежуточные обещания, возвращая обещания от последней функции <b>then</b> в цепочке. Например:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> someRenderer(itemPromise) {<br />    <span style="color: rgb(0, 0, 255);">return</span> itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />        <span style="color: rgb(0, 0, 255);">return</span> doSomeWorkAsync(item.data);<br />    }).then(<span style="color: rgb(0, 0, 255);">function</span> (results) {<br />        <span style="color: rgb(0, 0, 255);">return</span> doMoreWorkAsync(results1);<br />    }).then(<span style="color: rgb(0, 0, 255);">function</span> (results2) {<br />        <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        <span style="color: rgb(0, 128, 0);">// use results2 to configure the element</span><br />        <span style="color: rgb(0, 0, 255);">return</span> element;<br />    });<br />}<br /></pre>
  </div>
</blockquote>

<p>Обратите внимание, что в этом случае мы <i>не</i> используем функцию <b>done</b> в конце цепочки, поскольку мы возвращаем обещание от последнего вызова функции <b>then</b>. ListView отвечает за обработку всех ошибок, которые могут возникнуть.</p>

<h2>Средства отрисовки заполнителя</h2>

<p>На следующем этапе оптимизации ListView используется <i>средство отрисовки заполнителя</i>, разделяющее формирование компонента на два этапа. Это позволяет ListView запрашивать части компонента, необходимые для определения общей разметки списка без создания всех компонентов каждого элемента. В результате ListView может быстро закончить этап разметки и при этом быстро реагировать на дальнейший ввод. Оставшиеся части компонента ListView может запросить позднее.</p>

<p>Средство отрисовки заполнителя возвращает объект с двумя свойствами, а не обещание:</p>

<ul>
  <li><i>element</i> — компонент верхнего уровня в структуре отображаемого элемента. Его достаточно для определения размера и формы, и он не зависит от данных элемента.</li>

  <li><i>renderComplete</i> — обещание, которое выполняется после формирования оставшихся частей компонента, т. е. когда возвращается обещание из цепочки, начинающейся с <b>itemPromise.then</b>, как и ранее.</li>
</ul>

<p>ListView реализован достаточно интеллектуально, поэтому он проверяет, возвращает ли средство отрисовки обещание (базовая ситуация, как описано ранее) или объект со свойствами <i>element</i> и <i>renderComplete</i> (более сложные ситуации). Таким образом, эквивалентное средство отрисовки заполнителя (в примере) для предыдущей функции <b>simpleRenderer</b> выглядит следующим образом:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> placeholderRenderer(itemPromise) {<br />    <span style="color: rgb(0, 128, 0);">// create a basic template for the item that doesn't depend on the data</span><br />    <span style="color: rgb(0, 0, 255);">var</span> element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />    element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />    element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;div class='content'&gt;...&lt;/div&gt;&quot;</span>;<br /><br />    <span style="color: rgb(0, 128, 0);">// return the element as the placeholder, and a callback to update it when data is available</span><br />    <span style="color: rgb(0, 0, 255);">return</span> {<br />        element: element,<br /><br />        <span style="color: rgb(0, 128, 0);">// specifies a promise that will be completed when rendering is complete</span><br />        <span style="color: rgb(0, 128, 0);">// itemPromise will complete when the data is available</span><br />        renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />            <span style="color: rgb(0, 128, 0);">// mutate the element to include the data</span><br />            element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>).innerText = item.data.title;<br />            element.insertAdjacentHTML(<span style="color: rgb(0, 96, 128);">&quot;afterBegin&quot;</span>, <span style="color: rgb(0, 96, 128);">&quot;&lt;img src='&quot;</span> +<br />                item.data.thumbnail + <span style="color: rgb(0, 96, 128);">&quot;' alt='Databound image' /&gt;&quot;</span>);<br />        })<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Обратите внимание на то, что назначение <i>element.innerHTML</i> можно было бы переместить в <b>renderComplete</b>, поскольку класс <i>itemTempl</i> в файле css/scenario1.css примера напрямую определяет ширину и высоту элемента. Это назначение указано в свойстве <i>element</i>, потому что оно задает в заполнителе текст по умолчанию "…". Вы можете так же просто использовать компонент <i>img</i>, который ссылается на небольшой ресурс в пакете, общий для всех элементов (и поэтому быстро визуализируемый).</p>

<h2>Средства отрисовки заполнителя с повторным использованием</h2>

<p>Следующая возможность оптимизации — применение средства отрисовки <i>заполнителя с повторным использованием</i> — не добавляет ничего нового в отношении обещаний. Она добавляет знание о втором параметре средства отрисовки, <i>recycled</i>, который является корневым компонентом ранее отрисованного элемента, который больше не виден. Это значит, что дочерние компоненты повторно используемого компонента уже сформированы, поэтому можно просто заменить данные и, возможно, подправить несколько компонентов. Так можно избежать ресурсоемких вызовов создания компонентов, необходимых для отображения совершенно нового элемента. Это позволяет сэкономить много времени в процессе отрисовки.</p>

<p>ListView может предоставить повторно используемый компонент, если для его свойства <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211835.aspx" target="_blank">loadingBehavior</a><b></b> задано значение "randomaccess". Если указан параметр <i>recycled</i>, можно просто удалить данные этого компонента (и его дочерних компонентов), вернуть его как заполнитель, а затем вставить в него данные и создать дополнительные дочерние компоненты (при необходимости) в <i>renderComplete</i>. Если повторно используемый компонент не указан (как при первом создании ListView или если для параметра <b>loadingBehavior</b> задано значение "incremental"), компонент создается заново. Вот код из примера для этого варианта:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> recyclingPlaceholderRenderer(itemPromise, recycled) {<br />    <span style="color: rgb(0, 0, 255);">var</span> element, img, label;<br />    <span style="color: rgb(0, 0, 255);">if</span> (!recycled) {<br />        <span style="color: rgb(0, 128, 0);">// create a basic template for the item that doesn't depend on the data</span><br />        element = document.createElement(<span style="color: rgb(0, 96, 128);">&quot;div&quot;</span>);<br />        element.className = <span style="color: rgb(0, 96, 128);">&quot;itemTempl&quot;</span>;<br />        element.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;&lt;img alt='Databound image' style='visibility:hidden;'/&gt;&quot;</span> +<br />            <span style="color: rgb(0, 96, 128);">&quot;&lt;div class='content'&gt;...&lt;/div&gt;&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// clean up the recycled element so that we can reuse it </span><br />        element = recycled;<br />        label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>);<br />        label.innerHTML = <span style="color: rgb(0, 96, 128);">&quot;...&quot;</span>;<br />        img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>);<br />        img.style.visibility = <span style="color: rgb(0, 96, 128);">&quot;hidden&quot;</span>;<br />    }<br />    <span style="color: rgb(0, 0, 255);">return</span> {<br />        element: element,<br />        renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />            <span style="color: rgb(0, 128, 0);">// mutate the element to include the data</span><br />            <span style="color: rgb(0, 0, 255);">if</span> (!label) {<br />                label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>);<br />                img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>);<br />            }<br />            label.innerText = item.data.title;<br />            img.src = item.data.thumbnail;<br />            img.style.visibility = <span style="color: rgb(0, 96, 128);">&quot;visible&quot;</span>;<br />        })<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>В <i>renderComplete</i> необходимо проверить наличие компонентов, которые не создаются для нового заполнителя, например <i>label</i>, и создать их при необходимости.</p>

<p>Если вы хотите очистить повторно используемые элементы с помощью более общего процесса, можно создать функцию для свойства <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211846.aspx" target="_blank">resetItem</a><b></b> элемента управления ListView. Эта функция будет содержать код, аналогичный приведенному выше. То же относится и к свойству <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh700726.aspx" target="_blank">resetGroupHeader</a><b></b>, поскольку вы можете использовать функции шаблона для заголовков групп и элементов. Мы не обсуждали их подробно, поскольку заголовков групп не так много и обычно они не так сильно влияют на производительность. Но тем не менее такая возможность существует.</p>

<h2>Средства многоэтапной отрисовки</h2>

<p>Теперь перейдем к предпоследней возможности оптимизации — <i>средству многоэтапной отрисовки</i>. Оно расширяет возможности средства отрисовки заполнителя с повторным использованием, задерживая загрузку изображений и других объектов мультимедиа, пока весь элемент не появится в DOM. Оно также задерживает эффекты, например анимацию, пока элемент не появится на экране. Это связано с тем, что зачастую пользователи довольно быстро перемещаются по элементу управления ListView, поэтому имеет смысл асинхронно отложить более ресурсоемкие операции, пока ListView не окажется в стабильном положении.</p>

<p>ListView предоставляет необходимые обработчики как члены <b>item</b>, полученного от <b>itemPromise</b>: свойство <b>ready</b> (обещание) и два метода, <b>loadImage</b> и <b>isOnScreen</b>, также возвращающие обещания. Т. е.:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// item.ready, item.loadImage, and item.isOnScreen available</span><br />})<br /></pre>
  </div>
</blockquote>

<p>Вот как они используются:</p>

<ul>
  <li><b>ready</b> — возвращайте это обещание из первого обработчика выполнения в цепочке. Это обещание выполняется, когда полная структура элемента отрисована и видима. Это значит, что другой метод <b>then</b> можно объединить с обработчиком выполнения, в котором выполняются другие операции, такие как загрузка изображений.</li>

  <li><b>loadImage</b> — загружает изображение по URI и отображает его в указанном компоненте <i>img</i>, возвращая обещание, которое выполняется с тем же элементом. Обработчик выполнения присоединяется к этому обещанию, которое само возвращает обещание от <b>isOnScreen</b>. Обратите внимание, что <b>loadImage</b> создает компонент <i>img</i>, если он не указан, и предоставляет его обработчику выполнения.</li>

  <li><b>isOnScreen</b> — возвращает обещание с логическим значением выполнения, указывающим, видим элемент или нет. В текущих реализациях это известное значение, поэтому обещание выполняется синхронно. Однако, заключив в обещание, его можно использовать в более длинной цепочке.</li>
</ul>

<p>Все это видно в функции <b>multistageRenderer</b> в примере, где завершение загрузки изображения используется для начала анимации исчезания. Здесь я просто покажу, что возвращает обещание <i>renderComplete</i>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// mutate the element to update only the title</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!label) { label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>); }<br />    label.innerText = item.data.title;<br /><br />    <span style="color: rgb(0, 128, 0);">// use the item.ready promise to delay the more expensive work</span><br />    <span style="color: rgb(0, 0, 255);">return</span> item.ready;<br />    <span style="color: rgb(0, 128, 0);">// use the ability to chain promises, to enable work to be cancelled</span><br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// use the image loader to queue the loading of the image</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!img) { img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>); }<br />    <span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail, img).then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />        <span style="color: rgb(0, 128, 0);">// once loaded check if the item is visible</span><br />        <span style="color: rgb(0, 0, 255);">return</span> item.isOnScreen();<br />    });<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (onscreen) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (!onscreen) {<br />        <span style="color: rgb(0, 128, 0);">// if the item is not visible, don't animate its opacity</span><br />        img.style.opacity = 1;<br />    } <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// if the item is visible, animate the opacity of the image</span><br />        WinJS.UI.Animation.fadeIn(img);<br />    }<br />})<br /></pre>
  </div>
</blockquote>

<p>Хотя и происходит много всего, здесь используется всего лишь базовая цепочка обещаний. Первая асинхронная операция в средстве отрисовки обновляет простые части структуры компонентов элемента, такие как текст. Затем она возвращает обещание в <b>item.ready</b>. Когда это обещание выполняется или, говоря точнее, если оно выполняется, мы используем асинхронный метод <b>loadImage</b> элемента, чтобы инициировать загрузку изображения. Обработчик выполнения возвращает обещание <b>item.isOnScreen</b>. Это значит, что флаг видимости <i>onscreen</i> передается в конечный обработчик выполнения в цепочке. Если и когда обещание <b>isOnScreen</b> выполняется (элемент полностью видим), мы можем заняться соответствующими операциями, например анимацией.</p>

<p>Я подчеркиваю часть с "если", так как есть вероятность, что пользователь быстро перемещается по элементу управления ListView, когда все это происходит. Объединив все обещания в цепочку, мы позволяем ListView отменять асинхронные операции, если эти элементы выходят из поля зрения или за пределы страниц, хранящихся в буфере. Достаточно сказать, что производительность элемента управления ListView была <i>тщательно</i> протестирована!</p>

<p>Также важно напомнить еще раз, что во всех этих цепочках мы используем <b>then</b>, потому что функция отрисовки в свойстве <i>renderComplete</i> возвращает обещание. Эти функции отрисовки никогда не будут концом цепочки, поэтому <b>done</b> никогда не будет использоваться.</p>

<h2>Пакетная обработка эскизов</h2>

<p>Последняя возможность оптимизации — это воистину <i>Священный Грааль</i> для элемента управления ListView. В функции <b>batchRenderer</b> мы находим следующую структуру для <i>renderComplete</i> (большая часть кода опущена):</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">renderComplete: itemPromise.then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// mutate the element to update only the title</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!label) { label = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;.content&quot;</span>); }<br />    label.innerText = item.data.title;<br /><br />    <span style="color: rgb(0, 128, 0);">// use the item.ready promise to delay the more expensive work</span><br />    <span style="color: rgb(0, 0, 255);">return</span> item.ready;<br />    <span style="color: rgb(0, 128, 0);">// use the ability to chain promises, to enable work to be cancelled</span><br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (item) {<br />    <span style="color: rgb(0, 128, 0);">// use the image loader to queue the loading of the image</span><br />    <span style="color: rgb(0, 0, 255);">if</span> (!img) { img = element.querySelector(<span style="color: rgb(0, 96, 128);">&quot;img&quot;</span>); }<br />    <span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail, img).then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />        <span style="color: rgb(0, 128, 0);">// once loaded check if the item is visible</span><br />        <span style="color: rgb(0, 0, 255);">return</span> item.isOnScreen();<br />    });<br />}).then(<span style="color: rgb(0, 0, 255);">function</span> (onscreen) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (!onscreen) {<br />        <span style="color: rgb(0, 128, 0);">// if the item is not visible, don't animate its opacity</span><br />        img.style.opacity = 1;<br />    } <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// if the item is visible, animate the opacity of the image</span><br />        WinJS.UI.Animation.fadeIn(img);<br />    }<br />})<br /></pre>
  </div>
</blockquote>

<p>Она практически совпадает со структурой для <b>multistageRenderer</b>, за исключением загадочного вызова функции <b>thumbnailBatch</b> между вызовом <b>item.loadImage</b> и проверкой свойства <b>item.isOnScreen</b>. Наличие <b>thumbnailBatch</b> в цепочке указывает на то, что возвращаемым значением должен быть обработчик выполнения, возвращающий еще одно обещание.</p>

<p>Запутались? Ничего страшного, мы во всем разберемся. Но сначала мы должны побольше узнать о том, чего пытаемся добиться.</p>

<p>Если бы в ListView был всего один элемент, различные способы оптимизации загрузки были бы незаметны. Но в ListView обычно содержится множество элементов, и функция отрисовки вызывается для каждого из них. В функции <b>multistageRenderer</b> из предыдущего раздела отрисовка каждого элемента инициирует асинхронную операцию <b>item.loadImage</b> для загрузки эскиза из произвольного URI. Каждая такая операция может занять определенное время. Поэтому для всего списка может одновременно выполняться много вызовов <b>loadImage</b>, причем отрисовка каждого элемента будет ожидать завершения обработки соответствующего эскиза. Пока все понятно.</p>

<p>Важная характеристика, которая совсем не видна в <b>multistageRenderer</b>, состоит в том, что компонент <i>img</i> для эскиза <i>уже</i> находится в DOM, а функция <b>loadImage</b> устанавливает атрибут <i>src</i> этого изображения после завершения загрузки. Это в свою очередь инициирует обновление модуля отрисовки после возврата из оставшейся цепочки обещаний, которая после этой точки выполняется синхронно.</p>

<p>Может случиться так, что множество эскизов вернутся в поток пользовательского интерфейса через короткое время. Это приведет к усложнению работы модуля отрисовки и низкой производительности визуализации. Чтобы избежать этого, компоненты <i>img</i> необходимо полностью создать <i>до</i> их помещения в DOM, а затем добавить в пакеты для обработки в одном цикле отрисовки.</p>

<p>В примере это реализуется с помощью обещаний — функции <b>createBatch</b>. <b>createBatch</b> вызывается один раз для всего приложения, а ее результат (другая функция) сохраняется в переменной <b>thumbnailBatch</b>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> thumbnailBatch;<br />thumbnailBatch = createBatch();<br /></pre>
  </div>
</blockquote>

<p>Вызов этой функции <b>thumbnailBatch</b>, как я ее буду теперь называть, снова вставляется в цепочку обещаний функции отрисовки. Цель этой вставки с учетом природы кода пакетной обработки (как мы скоро увидим) — сгруппировать набор загруженных компонентов <i>img</i>, освободив их для дальнейшей обработки через подходящие интервалы. Если посмотреть на цепочку обещаний в функции отрисовки, вызов <b>thumbnailBatch()</b> должен вернуть функцию обработчика выполнения, возвращающую обещание. Значением выполнения этого обещания (если посмотреть на следующее звено в цепочке) должен быть компонент <i>img</i>, который можно добавить в DOM. Добавляя изображения в DOM <i>после</i> пакетной обработки, мы обрабатываем эту группу в одном цикле отрисовки.</p>

<p>В этом состоит важное отличие <b>batchRenderer</b> от функции <b>multistageRenderer</b> из предыдущего раздела: в последней из этих двух функций компонент <i>img</i> уже существует в DOM и передается в <b>loadImage</b> как второй параметр. Поэтому когда <b>loadImage</b> устанавливает атрибут <i>src</i> изображения, инициируется обновление отрисовки. А в функции <b>batchRenderer</b> элемент <i>img</i> создается отдельно в <b>loadImage</b> (где атрибут <i>src</i> также установлен), но элемента <i>img</i> еще нет в DOM. Он будет добавлен в DOM только после выполнения <b>thumbnailBatch</b>, что делает его частью группы на этом этапе разметки.</p>

<p>Теперь рассмотрим, как действует пакетная обработка. Далее представлена полная функция <b>createBatch</b>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> createBatch(waitPeriod) {<br />    <span style="color: rgb(0, 0, 255);">var</span> batchTimeout = WinJS.Promise.<span style="color: rgb(0, 0, 255);">as</span>();<br />    <span style="color: rgb(0, 0, 255);">var</span> batchedItems = [];<br /><br />    <span style="color: rgb(0, 0, 255);">function</span> completeBatch() {<br />        <span style="color: rgb(0, 0, 255);">var</span> callbacks = batchedItems;<br />        batchedItems = [];<br />        <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = 0; i &lt; callbacks.length; i++) {<br />            callbacks[i]();<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> () {<br />        batchTimeout.cancel();<br />        batchTimeout = WinJS.Promise.timeout(waitPeriod || 64).then(completeBatch);<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />            batchedItems.push(c);<br />        });<br /><br />        <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />            <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                <span style="color: rgb(0, 0, 255);">return</span> v;<br />            });<br />        };<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Опять функция <b>createBatch</b> вызывается всего <i>один раз</i>, а ее результат, функция <b>thumbnailBatch</b>, вызывается для <i>каждого </i>отрисованного элемента<i> </i>в списке. Обработчик выполнения, формируемый <b>thumbnailBatch</b>, вызывается после завершения каждой операции <b>loadImage</b>.</p>

<p>Такой обработчик выполнения можно было бы легко вставить в функцию отрисовки, но мы хотим скоординировать операции для <i>разных элементов</i>, а не для каждого из них. Для этого в начале функции <b>createBatch</b> создаются и инициализируются две переменные: <i>batchedTimeout</i>, инициализируемая как пустое обещание, и <i>batchedItems</i>, инициализируемая как изначально пустой массив функций. <b>createBatch</b> также объявляет функцию <b>completeBatch</b>, которая просто очищает <i>batchedItems</i>, вызывая каждую функцию в массиве:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">function</span> createBatch(waitPeriod) {<br />    <span style="color: rgb(0, 0, 255);">var</span> batchTimeout = WinJS.Promise.<span style="color: rgb(0, 0, 255);">as</span>();<br />    <span style="color: rgb(0, 0, 255);">var</span> batchedItems = [];<br /><br />    <span style="color: rgb(0, 0, 255);">function</span> completeBatch() {<br />        <span style="color: rgb(0, 0, 255);">var</span> callbacks = batchedItems;<br />        batchedItems = [];<br />        <span style="color: rgb(0, 0, 255);">for</span> (<span style="color: rgb(0, 0, 255);">var</span> i = 0; i &lt; callbacks.length; i++) {<br />            callbacks[i]();<br />        }<br />    }<br /><br />    <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> () {<br />        batchTimeout.cancel();<br />        batchTimeout = WinJS.Promise.timeout(waitPeriod || 64).then(completeBatch);<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />            batchedItems.push(c);<br />        });<br /><br />        <span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />            <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                <span style="color: rgb(0, 0, 255);">return</span> v;<br />            });<br />        };<br />    };<br />}<br /></pre>
  </div>
</blockquote>

<p>Теперь посмотрим, что происходит в функции <b>thumbnailBatch</b> (возвращаемой <b>createBatch</b>), которая опять вызывается для каждого отображаемого элемента. Сначала мы <i>отменяем</i> любую существующую функцию <i>batchedTimeout</i> и сразу же повторно создаем ее:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">batchTimeout<span style="color: rgb(255, 0, 0);">.</span>cancel();<br />        batchTimeout = WinJS<span style="color: rgb(255, 0, 0);">.</span>Promise<span style="color: rgb(255, 0, 0);">.</span>timeout(waitPeriod || 64)<span style="color: rgb(255, 0, 0);">.</span>then(completeBatch);<br /></pre>
  </div>
</blockquote>

<p>Во второй строке показан шаблон будущей доставки или выполнения, описанный в записи "Все об обещаниях" &lt;TODO: link>: функция <b>completeBatch</b> вызывается после задержки в <i>waitPeriod</i> мс (значение по умолчанию — 64 мс). Это значит, что если <b>thumbnailBatch</b> опять вызывается в течение <i>waitPeriod</i> с момента предыдущего вызова, <b>batchTimeout</b> сбрасывается и устанавливается другое значение <i>waitPeriod</i>. Поскольку функция <b>thumbnailBatch</b> вызывается только <i>после </i>завершения вызова <b>item.loadImage</b>, можно сказать, что все операции <b>loadImage</b>, завершающиеся в течение <i>waitPeriod</i> предыдущего вызова, будут включены в один пакет. Если задержка превышает <i>waitPeriod</i>, выполняется обработка пакета (изображения добавляются в DOM) и начинается следующий пакет.</p>

<p>После этого <b>thumbnailBatch</b> создает новое обещание, которое просто записывает функцию диспетчера выполнения в массив <i>batchedItems</i>:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> delayedPromise = <span style="color: rgb(0, 0, 255);">new</span> WinJS.Promise(<span style="color: rgb(0, 0, 255);">function</span> (c) {<br />         batchedItems.push(c);<br />     });<br /></pre>
  </div>
</blockquote>

<p>Помните, в записи "Все об обещания" &lt;TODO: link> было сказано, что обещание — это просто конструкция кода. Это можно сказать и сейчас. Новое обещание не содержит асинхронных операций: мы просто добавляем функцию диспетчера выполнения, <i>c</i>, в <i>batchedItems</i>. Но, разумеется, мы ничего не делаем с диспетчером, пока <i>batchedTimeout</i> не будет выполнена асинхронно. Так что здесь есть асинхронная связь. Когда истекает период ожидания и мы очищаем пакет (в функции <b>completeBatch</b>), мы вызываем все указанные обработчики выполнения в методе <b>delayedPromise.then</b>.</p>

<p>Перейдем к последним строкам кода в <b>createBatch</b> — функции, возвращаемой <b>thumbnailBatch</b>. Эта функция — обработчик выполнения, вставляемый в цепочку обещаний функции отрисовки:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">return</span> <span style="color: rgb(0, 0, 255);">function</span> (v) {<br />           <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />               <span style="color: rgb(0, 0, 255);">return</span> v;<br />           });<br />       };<br /></pre>
  </div>
</blockquote>

<p>Давайте добавим этот фрагмент кода напрямую в цепочку обещаний, чтобы увидеть полученные связи:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">return</span> item.loadImage(item.data.thumbnail);<br />          }).then(<span style="color: rgb(0, 0, 255);">function</span> (v) {<br />              <span style="color: rgb(0, 0, 255);">return</span> delayedPromise.then(<span style="color: rgb(0, 0, 255);">function</span> () {<br />                  <span style="color: rgb(0, 0, 255);">return</span> v;<br />              });<br />          ).then(<span style="color: rgb(0, 0, 255);">function</span> (newimg) {<br /></pre>
  </div>
</blockquote>

<p>Теперь мы видим, что аргумент <i>v</i> — это результат <b>item.loadImage</b>, т. е. компонент <i>img</i>, созданный для нас. Если бы мы не хотели выполнять пакетную обработку, мы могли бы просто добавить выражение <b>return WinJS.Promise.as(v)</b>, и вся цепочка все равно бы работала: аргумент <i>v</i> передавался бы асинхронно и отображался как <i>newimg</i> на следующем этапе.</p>

<p>Вместо этого мы возвращаем обещание из <b>delayedPromise.then</b>, которое не будет выполнено (с аргументом <i>v</i>), пока не выполнено обещание <i>batchedTimeout</i>. В это время (если между завершением операций <b>loadImage</b> есть задержка не меньше <i>waitPeriod</i>) данные компоненты <i>img</i> передаются на следующий этап цепочки, где они добавляются в DOM.</p>

<p>Вот и все!</p>

<h2>Заключение</h2>

<p>У пяти разных функций отрисовки, продемонстрированных в <a href="http://code.msdn.microsoft.com/windowsapps/ListView-performance-39fb71f0" target="_blank">примере оптимизации производительности HTML ListView</a>, есть одна общая черта: они показывают, как асинхронная связь между ListView и функцией отрисовки, выраженная обещаниями, делает функцию отрисовки невероятно гибкой с точки зрения способа и времени создания элементов в списке. При написании собственных приложений стратегия оптимизации ListView сильно зависит от размера источника данных, сложности самих элементов, объема получаемых асинхронно данных для них (например, при загрузке удаленных изображений). Очевидно, для достижения необходимой производительности функции отрисовки элементов должны быть максимально простыми. Но в любом случае теперь у вас есть все инструменты, необходимые для обеспечения оптимальной производительности ListView (и вашего приложения).</p>

<p>Крэйг Брокшмидт (Kraig Brockschmidt) 
  <br />Руководитель программы, рабочая группа по экосистеме Windows 

  <br />Автор книги <a href="http://blogs.msdn.com/b/microsoft_press/archive/2012/10/29/free-ebook-programming-windows-8-apps-with-html-css-and-javascript.aspx"><i>Programming Windows 8 Apps in HTML, CSS, and JavaScript (Программирование приложений для Windows 8 на HTML, CSS и JavaScript)</i></a></p>
<!-- Title: “Оптимизация отрисовки элементов ListView” Tags: “Приложения Магазина Windows, отрисовка, пакетная обработка, пакет, визуализация, ListView” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Примите участие в мероприятии Game On Virtual Event</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/game-on-virtua</link>
      <pubDate>Wed, 12 Jun 2013 11:43:16 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/06/12/game-on-virtua/</guid>
      <description><![CDATA[Игры составляют ключевой класс приложений в Магазине Windows. Если вы собираетесь создать игру для...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Игры составляют ключевой класс приложений в Магазине Windows. Если вы собираетесь создать игру для Магазина Windows, мы поможем вам на этом виртуальном мероприятии, посвященном созданию игр. В этом бесплатном мероприятии могут принять участие как начинающие разработчики игр, так и профессионалы. </p>  <p>Мы будем использовать <a href="https://aka.ms/yoyogamesgamemaker" target="_blank">GameMaker: Studio</a> от компании YoYo Games, чтобы показать вам, как создавать и публиковать высококачественные игры, тратя на это меньше времени. В GameMaker:Studio есть встроенные варианты разработки и инструменты, используемые с помощью перетаскивания, благодаря которым можно быстро приступить к работе над игрой, даже если вы еще не придумали идею игры или не имеете опыта разработки игр. Однако более опытные разработчики игр могут использовать более развитые инструменты для создания уникального игрового пространства. </p>  <p><a href="https://aka.ms/gameonevent"><img title="clip_image002" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8666.clip_image002_0385EAB3.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8666.clip_5F00_image002_5F00_0385EAB3.jpg" width="500" height="154" /></a></p>  <p>Это интернет-мероприятие начнется в субботу 15<sup></sup> июня в 10 утра по Тихоокеанскому летнему времени с открывающего сеанса и интерактивного чата. Вы узнаете о различных видах игр и о том, как добавлять графику, уровни и звук к базовым играм и использовать способы, позволяющие сделать вашу игру своеобразной и неповторимой. На протяжении недели будет предоставляться техническая поддержка в виде индивидуальной помощи через форумы GameMaker.</p>  <p>Независимо от того, являетесь ли вы студентом, начинающим разработчиком или опытным профессионалом, это мероприятие поможет вам приступить к созданию, загрузке и публикации игр в Магазине Windows. Узнайте подробности, зарегистрируйтесь для участия и ознакомьтесь с бесплатными инструментами и ресурсами на сайте <a href="http://msdnevents.com/gameon/" target="_blank">http://msdnevents.com/gameon/</a>. </p>  <p>-- Роберт Родригез-Лоусон (Robert Rodriguez-Lawson), ведущий руководитель по публикации контента, отдел контента для разработчиков для Windows</p> <!-- Title: “Примите участие в мероприятии Game On Virtual Event” Tags: “игры для Магазина Windows, игры, Game On, мероприятия” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Хранилище учетных данных — удобное решение для обработки имен пользователей и паролей в вашем приложении Магазина Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/53</link>
      <pubDate>Tue, 04 Jun 2013 19:45:00 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/06/04/53/</guid>
      <description><![CDATA[Если вы еще не слышали о хранилище учетных данных, доступном для приложений Магазина Windows,...]]></description>
      <content:encoded><![CDATA[<div class="PostContent">
<p>Если вы еще не слышали о <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465069.aspx" target="_blank">хранилище учетных данных</a>, доступном для приложений Магазина Windows, сейчас самое время познакомиться с ним. Почему? Потому что оно не только упрощает задачу <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465060.aspx" target="_blank">хранения</a> и <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/jj839731.aspx" target="_blank">получения учетных данных пользователя</a>, но и обеспечивает безопасное хранение и "бесплатное" перемещение учетных данных пользователя вместе с его учетной записью Майкрософт.</p>
<p>Предположим, у вас есть приложение, подключающееся к службе для доступа к защищенным ресурсам, например к мультимедийным файлам, социальным сетям и т. п. Ваша служба требует ввода учетных данных для каждого пользователя. Поэтому вы встроили в свое приложение интерфейс для ввода имени пользователя и пароля, которые затем используются для входа в службу. Все работает как часы.</p>
<p>Теперь вы хотите упростить жизнь пользователям вашего приложения и сохранить их учетные данные в безопасном месте, чтобы им не приходилось выполнять вход каждый раз при использовании вашего приложения. Воспользуйтесь для этого хранилищем учетных данных. Несколько простых вызовов API-интерфейса Credential Locker позволяют сохранить имя пользователя и пароль и легко получить эти данные для выполнения входа в следующий раз, когда пользователь откроет ваше приложение.</p>
<h2>Безопасное хранилище</h2>
<p>Важное преимущество использования хранилища учетных данных в ваших приложениях заключается в том, что оно позволяет хранить учетные данные пользователя в безопасном месте, причем учетные данные шифруются при записи на диск. Разумеется, вы могли бы хранить учетные данные пользователя для вашего приложения в файле в локальном хранилище, но хранение учетных данных в текстовом формате связано с серьезным риском для безопасности. Если система пользователя каким-либо образом подвергнута опасности, злоумышленнику легко получить доступ к имени пользователя и паролю и использовать их в своих целях. Если имя пользователя и пароль хранятся с использованием хранилища учетных данных, злоумышленник получит только зашифрованный файл.</p>
<p>Хранилище учетных данных является уникальным для каждого пользователя компьютера с Windows. Доступ к учетным данным имеет только приложение, сохранившее их. То есть вы можете получить только те учетные данные, которые сохранили для вашего приложения. Никакие другие приложения не могут получить доступ к учетным данным, помещенным в хранилище вашим приложением.</p>
<h2>Перемещение учетных данных</h2>
<p>Ваши пользователи получают еще и дополнительное преимущество: когда вы сохранили для них имя пользователя и пароль в хранилище учетных данных, сохраненные учетные данные перемещаются вместе с их учетной записью Майкрософт на любой другой доверенный компьютер, используемый ими с этой учетной записью Майкрософт. Благодаря этому ваше безопасное приложение становится еще более удобным для пользователей, поскольку может обеспечить для них автоматический вход &mdash; без повторного ввода учетных данных &mdash; с любого доверенного компьютера, на котором они установили ваше приложение и который связан с их учетной записью Майкрософт.</p>
<p>В случае учетных записей домена все работает несколько иначе. Если есть учетные данные, сохраненные вместе с учетной записью Майкрософт, и вы связываете эту учетную запись с доменной учетной записью (например, с учетной записью, используемой на работе), ваши учетные данные будут перемещены в эту доменную учетную запись. Однако все новые учетные данные, добавленные после входа с использованием этой доменной учетной записи, перемещаться не будут. Это гарантирует, что закрытые учетные данные для данного домена не будут доступны за его пределами.</p>
<h2>Сохранение учетных данных пользователя</h2>
<p>Сохранение учетных данных пользователя в хранилище учетных данных &mdash; быстрый процесс, состоящий из двух этапов. Сначала вы получаете ссылку на хранилище учетных данных, используя объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a> из пространства имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a>. Затем вы создаете объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordcredential.aspx" target="_blank">PasswordCredential</a>, содержащий идентификатор для вашего приложения, имя пользователя и пароль, и передаете эту информацию методу <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh701231.aspx" target="_blank">PasswordVault.Add()</a>, чтобы добавить эти учетные данные в хранилище.</p>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;">var vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.Add(<span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: #006080;">"My App"</span>, username, password));</pre>
</div>
</blockquote>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">var</span> vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.add(<span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: #006080;">"My App"</span>, username, password));</pre>
</div>
</blockquote>
<h2>Получение учетных данных пользователя</h2>
<p>У вас есть несколько вариантов получения учетных данных пользователя из хранилища учетных данных, когда у вас есть ссылка на объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a>.</p>
<ul>
<li>Вы можете получить все учетные данные, предоставленные пользователем для вашего приложения в хранилище, с помощью метода <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.retrieveall.aspx" target="_blank">PasswordVault.RetrieveAll()</a>.</li>
<li>Если вы знаете имя пользователя для сохраненных учетных данных, то можете получить все учетные данные для этого имени пользователя с помощью метода <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.findallbyusername.aspx" target="_blank">PasswordVault.FindAllByUserName()</a>.</li>
<li>Если вы знаете имя ресурса для сохраненных учетных данных, то можете получить все учетные данные для этого имени ресурса с помощью метода <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.findallbyresource.aspx" target="_blank">PasswordVault.FindAllByResource()</a>.</li>
<li>Наконец, если вы знаете и имя пользователя, и имя ресурса для учетных данных, то можете получить нужные учетные данные с помощью метода <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.retrieve.aspx" target="_blank">PasswordVault.Retrieve()</a>.</li>
</ul>
<p>Давайте рассмотрим пример, в котором мы глобально сохранили имя ресурса в приложении и автоматически выполняем вход за пользователя, если находим для него учетные данные. В этом случае, если мы нашли несколько учетных данных для этого пользователя, мы просим его выбрать те учетные данные, которые должны по умолчанию использоваться для входа.</p>
<p><strong>C#</strong></p>
<blockquote>
<div>
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> resourceName = <span style="color: #006080;">"My App"</span>;<br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> defaultUserName;<br /><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> Login()<br />{<br />    var loginCredential = GetCredentialFromLocker();<br /><br />    <span style="color: #0000ff;">if</span> (loginCredential != <span style="color: #0000ff;">null</span>)<br />    {<br />        <span style="color: #008000;">// There is a credential stored in the locker.</span><br />        <span style="color: #008000;">// Populate the Password property of the credential</span><br />        <span style="color: #008000;">// for automatic login.</span><br />        loginCredential.RetrievePassword();<br />    }<br />    <span style="color: #0000ff;">else</span><br />    {<br />        <span style="color: #008000;">// There is no credential stored in the locker.</span><br />        <span style="color: #008000;">// Display UI to get user credentials.</span><br />        loginCredential = GetLoginCredentialUI();<br />    }<br /><br />    <span style="color: #008000;">// Log the user in.</span><br />    ServerLogin(loginCredential.UserName, loginCredential.Password);<br />}<br /><br /><br /><span style="color: #0000ff;">private</span> Windows.Security.Credentials.PasswordCredential GetCredentialFromLocker()<br />{<br />    Windows.Security.Credentials.PasswordCredential credential = <span style="color: #0000ff;">null</span>;<br /><br />    var vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />    var credentialList = vault.FindAllByResource(resourceName);<br />    <span style="color: #0000ff;">if</span> (credentialList.Count &gt; 0)<br />    {<br />        <span style="color: #0000ff;">if</span> (credentialList.Count == 1)<br />        {<br />            credential = credentialList[0];<br />        }<br />        <span style="color: #0000ff;">else</span><br />        {<br />            <span style="color: #008000;">// When there are multiple usernames,</span><br />            <span style="color: #008000;">// retrieve the default username. If one doesn&rsquo;t</span><br />            <span style="color: #008000;">// exist, then display UI to have the user select</span><br />            <span style="color: #008000;">// a default username.</span><br /><br />            defaultUserName = GetDefaultUserNameUI();<br /><br />            credential = vault.Retrieve(resourceName, defaultUserName);<br />        }<br />    }<br /><br />    <span style="color: #0000ff;">return</span> credential;<br />}</pre>
</div>
</blockquote>
<div><br /><strong>JavaScript</strong></div>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">var</span> resourceName = <span style="color: #006080;">"My App"</span>;<br /><span style="color: #0000ff;">var</span> defaultUserName;<br /><br /><span style="color: #0000ff;">function</span> login() {<br />    <span style="color: #0000ff;">var</span> loginCredential = getCredentialFromLocker();<br /><br />    <span style="color: #0000ff;">if</span> (loginCredential != <span style="color: #0000ff;">null</span>) {<br />        <span style="color: #008000;">// There is a credential stored in the locker.</span><br />        <span style="color: #008000;">// Populate the Password property of the credential</span><br />        <span style="color: #008000;">// for automatic login.</span><br />        loginCredential.retrievePassword();<br />    } <span style="color: #0000ff;">else</span> {<br />        <span style="color: #008000;">// There is no credential stored in the locker.</span><br />        <span style="color: #008000;">// Display UI to get user credentials.</span><br />        loginCredential = getLoginCredentialUI();<br />    }<br /><br />    <span style="color: #008000;">// Log the user in.</span><br />    serverLogin(loginCredential.userName, loginCredential.password);<br />}<br /><br /><br /><span style="color: #0000ff;">function</span> GetCredentialFromLocker() {<br />    <span style="color: #0000ff;">var</span> credential = <span style="color: #0000ff;">null</span>;<br /><br />    <span style="color: #0000ff;">var</span> vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />    <span style="color: #0000ff;">var</span> credentialList = vault.findAllByResource(resourceName);<br />    <span style="color: #0000ff;">if</span> (credentialList.length &gt; 0) {<br />        <span style="color: #0000ff;">if</span> (credentialList.length == 1) {<br />            credential = credentialList[0];<br />        } <span style="color: #0000ff;">else</span> {<br />            <span style="color: #008000;">// When there are multiple usernames,</span><br />            <span style="color: #008000;">// retrieve the default username. If one doesn&rsquo;t</span><br />            <span style="color: #008000;">// exist, display UI to have the user select</span><br />            <span style="color: #008000;">// a default username.</span><br /><br />            defaultUserName = getDefaultUserNameUI();<br />            credential = vault.retrieve(resourceName, defaultUserName);<br />        }<br />    }<br /><br />    <span style="color: #0000ff;">return</span> credential;<br />}</pre>
</div>
</blockquote>
<h2>Удаление учетных данных пользователя</h2>
<p>Удаление учетных данных пользователя из хранилища учетных данных также является быстрым процессом, выполняемым в два этапа. Вы получаете ссылку на хранилище учетных данных с использованием объекта <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.passwordvault.aspx" target="_blank">PasswordVault</a> из пространства имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a>. Затем вы передаете учетные данные, которые требуется удалить, методу <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh701242.aspx" target="_blank">PasswordVault.Remove()</a>.</p>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;">var vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.Remove(<span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: #006080;">"My App"</span>, username, password));</pre>
</div>
</blockquote>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">var</span> vault = <span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordVault();<br />vault.remove(<span style="color: #0000ff;">new</span> Windows.Security.Credentials.PasswordCredential(<br />    <span style="color: #006080;">"My App"</span>, username, password));</pre>
</div>
</blockquote>
<h2>Просто и безопасно</h2>
<p>Как видите, хранилище учетных данных &mdash; удобный компонент, упрощающий проверку подлинности пользователей и хранение их учетных данных для последующего использования и обеспечивающий высокий уровень безопасности.</p>
<p>Среди других средств проверки подлинности в приложениях для Windows 8 можно назвать <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465281.aspx" target="_blank">брокер веб-проверки подлинности</a>, который можно использовать для извлечения маркера проверки подлинности с сайта (например, OAuth), а также <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh770853.aspx" target="_blank">персонализацию вашего приложения на основе учетной записи Майкрософт пользователя</a>.</p>
<p>Дополнительную информацию можно найти в следующих статьях:</p>
<ul>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211367.aspx" target="_blank">Управление сведениями о пользователях (JavaScript)</a></li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/BR229572(v=win.10).aspx" target="_blank">Управление сведениями о пользователях (приложения Магазина Windows на языках C#/VB/C++ и XAML)</a></li>
<li><a href="http://code.msdn.microsoft.com/windowsapps/PasswordVault-f01be74a" target="_blank">Пример хранилища учетных данных</a></li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.security.credentials.aspx" target="_blank">Windows.Security.Credentials</a></li>
</ul>
<p>&nbsp;</p>
<p>&ndash; Дуг Ротхаус (Doug Rothaus), старший разработчик контента, отдел контента для разработчиков для Windows</p>
<p>Выражаем отдельную благодарность Яшару Бахману (Yashar Bahman) за помощь при создании этой статьи.</p>
<!-- Title: “Хранилище учетных данных — удобное решение для обработки имен пользователей и паролей в вашем приложении Магазина Windows” Tags: “получение учетных данных, хранение учетных данных, безопасное хранилище, хранилище учетных данных” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Создание приложений, учитывающих местоположение пользователя, с помощью пространства имен geolocation и приложения "Карты Bing</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/63</link>
      <pubDate>Tue, 28 May 2013 11:07:30 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/05/28/63/</guid>
      <description><![CDATA[Привязав расположение пользователя к бизнес-логике своего приложения, вы легко можете предоставлять...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Привязав расположение пользователя к бизнес-логике своего приложения, вы легко можете предоставлять пользователям прогноз погоды, купоны на скидку, расписание спортивных событий или концертов для того места, где они находятся. Воспользовавшись возможностями пространства имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229921.aspx" target="_blank">geolocation</a> в Windows 8, а также пакетом SDK для приложения "Карты Bing", вы можете создавать отличные <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx" target="_blank">приложения Магазина Windows, использующие данные о местоположении</a>.</p>  <p>Давайте подробнее рассмотрим, как ваше приложение может использовать <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br225603.aspx" target="_blank">службу определения местоположения</a> для предоставления пользователям информации с учетом их местоположения по таким показателям, как IP-адрес, сеть Wi-Fi или данные GPS. После определения расположения вы можете использовать пакет SDK для приложения "Карты Bing", чтобы показать пользователю, где он находится. </p>  <h2>Получение информации о расположении</h2>  <p>Для получения информации о расположении используется пространство имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.aspx">Windows.Devices.Geolocation</a>. Что именно используется для определения расположения пользователя — GPS, сеть Wi-Fi или IP-адрес, зависит от двух основных факторов:</p>  <ol>   <li>Требуемый уровень точности. Это оптимальный уровень точности, удовлетворяющий потребностям вашего приложения. </li>    <li>Доступность данных о расположении. Ведь датчиком GPS оснащены не все устройства. Кроме того, в момент запроса данных о местоположении подключение к сети или Wi-Fi может быть недоступно.</li> </ol>  <h3><a>Требуемая точность</a></h3>  <p>При запросе данных о расположении ваше приложение должно указать <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx" target="_blank">требуемую точность</a>, чтобы максимально быстро получить данные в пределах заданного диапазона. Каждый из типов расположения имеет определенные степени точности:</p>  <ul>   <li><a href="http://ru.wikipedia.org/wiki/Gps" target="_blank">GPS</a> — GPS обеспечивает наибольшую точность с погрешностью около 10 метров. Однако когда датчик GPS включается после длительного периода неактивности, ему требуется получить данные со спутника и затем триангулировать их, поэтому получение данных о расположении может занимать одну или две минуты. После установки соединения со спутниками GPS может получать данные о новом расположении гораздо быстрее. Конечно, чем дольше вы используете GPS, тем больше энергии на это расходуется. Чтобы разрешить системе GPS получать данные, следует установить для свойства <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx" target="_blank">Geolocator.DesiredAccuracy</a> значение High.</li>    <li><a href="http://ru.wikipedia.org/wiki/Wi-Fi" target="_blank">Wi-Fi</a> — подключение по Wi-Fi обеспечивает уровень точности с погрешностью от 300 до 500 метров. Если подключение уже установлено, данные о расположении можно получить быстрее, чем система GPS установит соединение со спутниками. Установите для свойства DesiredAccuracy значение Default, чтобы получить данные о расположении с помощью подключения по Wi-Fi.</li>    <li><a href="http://ru.wikipedia.org/wiki/IP_address" target="_blank">IP</a> — уровень точности при использовании IP-адреса может иметь погрешность до 1 километра. При наличии установленного подключения к сети данные о расположении можно получить быстрее, чем система GPS установит соединение со спутниками. Чтобы получить данные о расположении по IP-адресу, следует также установить значение Default для свойства DesiredAccuracy. Служба определения местоположения возвращает данные о расположении с максимально доступной точностью и указывает соответствующий уровень точности с помощью свойства <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geocoordinate.accuracy.aspx" target="_blank">Geocoordinate.Accuracy</a>.</li> </ul>  <p>Тщательно обдумайте и проанализируйте то, какой именно уровень точности вам необходим. Это может оказать влияние на показатели производительности и энергопотребления вашего приложения. Например, если приложение служит для получения прогноза погоды, высокая точность GPS в большинстве случаев не требуется. Кроме того, обязательно указывайте точность своих данных, отображая границы погрешности для возвращенных данных о расположении. Ниже приведен код C#, задающий требуемый уровень точности:</p>  <p><strong>C#</strong></p>  <blockquote>   <div id="codeSnippetWrapper">     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Geolocator geolocator = <span style="color: rgb(0, 0, 255);">new</span> Geolocator();<br />geolocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High;<br /></pre>
  </div>
</blockquote>

<br />Какая бы точность вам ни требовалась, вызов для определения расположения имеет следующий вид: 

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);</pre>
  </div>
</blockquote>

<p>Ниже приведен код JavaScript, который создает экземпляр класса Geolocator, задает требуемую точность, а затем определяет текущее расположение. Обратите внимание на то, что переменная "promise" в этом коде является объектом <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211867.aspx" target="_blank">WinJS.Promise</a>, поэтому для доступа к данным из вызова <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br225537.aspx" target="_blank">getGeopositionAsync</a> вам потребуется использовать метод <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh701079.aspx" target="_blank">done</a>.</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> geolocator = Windows.Devices.Geolocation.Geolocator();<br />geolocator.desiredAccuracy =<br />Windows.Devices.Geolocation.PositionAccuracy.high;<br /><br /><span style="color: rgb(0, 128, 0);">// Get the geoposition, capturing the request in a 'promise' object.</span><br /><span style="color: rgb(0, 0, 255);">var</span> promise = geolocator.getGeopositionAsync();<br /></pre>
  </div>
</blockquote>

<br />Помните о том, что в случае установки значения High для требуемой точности вы не можете быть уверены в способности устройства пользователя определять расположение с высокой точностью. Компьютер пользователя может не иметь датчика GPS, этот датчик может быть выключен, может отсутствовать подключение по Wi-Fi и т. д. Всегда будьте готовы гибко обрабатывать такие ситуации, в которых данные получаются с более низкой точностью. Как именно это реализовать, зависит от функциональных возможностей вашего приложения. Может ли оно продолжить работу с низкой точностью? Можно ли запросить уровень точности GPS? Подробнее эти вопросы рассматриваются в <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx" target="_blank">руководстве для приложений, использующих данные о местоположении</a>. 

<h3>Карты Bing</h3>

<p><a href="http://apps.microsoft.com/webpdp/app/97a2179c-38be-45a3-933e-0d2dbf14a142" target="_blank">Карты Bing</a> — это хороший пример приложения, адаптирующегося к изменениям точности доступных данных о расположении. На настольном компьютере, который обычно не имеет GPS и Wi-Fi, это приложение определяет расположение по IP-адресу и <a>выполняет масштабирование до уровня региона при отображении текущего местоположения на карте</a>. На ноутбуках, которые обычно имеют адаптер беспроводных сетей, это приложение использует сеть Wi-Fi для получения более точного расположения и дополнительного увеличения масштаба при просмотре карты текущего местоположения. Если пользователь еще больше увеличивает масштаб, значок текущего расположения показывает границы погрешности. На устройстве с системой GPS приложение "Карты Bing" получает данные о расположении с высокой точностью от GPS и более точно отображает это место на карте.</p>

<h3>Погода Bing</h3>

<p>Как уже было указано выше, такому приложению, как <a href="http://apps.microsoft.com/webpdp/app/421ba874-f903-4965-9b82-d60f3ba3cae0" target="_blank">Погода Bing</a>, требуется только информация на уровне региона. Поэтому такое приложение может указать, что нуждается только в низкой точности, и быстро получить данные о расположении. Это позволяет приложению активнее реагировать на действия и запросы пользователя. К другим приложениям, которым может потребоваться только информация на уровне региона, относятся подборки радиостанций, путеводители по магазинам или местные каналы новостей.</p>

<h2>Отображение данных о расположении с помощью пакета SDK для приложения "Карты Bing"</h2>

<p>После получения информации о расположении из вызова <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.getgeopositionasync.aspx" target="_blank">GetGeopositionAsync</a> вам потребуется отобразить ее на карте.</p>

<ul>
  <li>Сначала преобразуйте класс <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geoposition.aspx" target="_blank">Geoposition</a> в класс <a href="http://msdn.microsoft.com/ru-ru/library/hh846500.aspx" target="_blank">Location</a>, который можно использовать в приложении "Карты Bing". Для этого используйте следующий код:</li>
</ul>

<p> </p>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Location location = <span style="color: rgb(0, 0, 255);">new</span> Location(pos.Coordinate.Latitude, pos.Coordinate.Longitude);</pre>
  </div>
</blockquote>

<p><strong>JavaScript:</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">promise.done(<br />  <span style="color: rgb(0, 0, 255);">function</span> (pos) {<br />    <span style="color: rgb(0, 128, 0);">// Get the coordinates of the current location.</span><br />    <span style="color: rgb(0, 0, 255);">var</span> coord = pos.coordinate,<br />    location = <span style="color: rgb(0, 0, 255);">new</span> Microsoft.Maps.Location(coord.latitude, coord.longitude);<br /> <br />  },<br />  <span style="color: rgb(0, 0, 255);">function</span> (err) {<br />    <span style="color: rgb(0, 128, 0);">// Handle the error.</span><br />  });<br /></pre>
  </div>
</blockquote>

<p> </p>

<ul>
  <li>Затем отобразите местоположение с помощью приложения "Карты Bing". Пакет SDK для приложения "Карты Bing" можно получить <a href="http://visualstudiogallery.msdn.microsoft.com/bb764f67-6b2c-4e14-b2d3-17477ae1eaca">здесь</a>. Вам также потребуется получить ключ "Карты Bing", зарегистрировавшись на портале "Карты Bing" и выполнив инструкции по <a href="http://msdn.microsoft.com/ru-ru/library/ff428642.aspx">получению ключа "Карты Bing"</a>. Во время регистрации обязательно ознакомьтесь с ограничениями на использование каждого из типов ключей и выберите тот тип, который оптимально подходит для вашего приложения. 

    <br />Добавьте элемент управления "Карты Bing" в свой конструктор и вставьте ключ в учетные данные.</li>
</ul>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Page</span><br />    <span style="color: rgb(255, 0, 0);">xmlns</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:x</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:local</span><span style="color: rgb(0, 0, 255);">=&quot;using:SimpleMapping&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:d</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:mc</span><span style="color: rgb(0, 0, 255);">=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;</span><br />    <span style="color: rgb(255, 0, 0);">xmlns:Maps</span><span style="color: rgb(0, 0, 255);">=&quot;using:Bing.Maps&quot;</span><br />    <span style="color: rgb(255, 0, 0);">x:Class</span><span style="color: rgb(0, 0, 255);">=&quot;SimpleMapping.MainPage&quot;</span><br />    <span style="color: rgb(255, 0, 0);">mc:Ignorable</span><span style="color: rgb(0, 0, 255);">=&quot;d&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br /><br />    <span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Grid</span> <span style="color: rgb(255, 0, 0);">Background</span><span style="color: rgb(0, 0, 255);">=&quot;{StaticResource ApplicationPageBackgroundThemeBrush}&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br />        <span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Maps:Map</span> <span style="color: rgb(255, 0, 0);">x:Name</span><span style="color: rgb(0, 0, 255);">=&quot;Map&quot;</span> <span style="color: rgb(255, 0, 0);">Margin</span><span style="color: rgb(0, 0, 255);">=&quot;0,120,0,0&quot;</span> <span style="color: rgb(255, 0, 0);">Credentials</span><span style="color: rgb(0, 0, 255);">=&quot;Insert Your Bing Maps Key Here&quot;</span><span style="color: rgb(0, 0, 255);">/&gt;</span><br />    <span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">Grid</span><span style="color: rgb(0, 0, 255);">&gt;</span><br /><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">Page</span><span style="color: rgb(0, 0, 255);">&gt;</span></pre>
  </div>
</blockquote>

<ul>
  <li>Теперь вы можете использовать следующий код на странице приложения, где отображается карта. Он задает уровень масштабирования карты и отображает расположение. Подробнее об уровне масштабирования рассказано в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/jj850315.aspx" target="_blank">Отображение местоположения на карте Bing</a>:</li>
</ul>

<p><strong>C#</strong></p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">double</span> zoomLevel = 13.0f;<br /><br />Map.SetView(location, zoomLevel);<br /></pre>
  </div>
</blockquote>

<br />Чтобы добавить элемент управления "Карты Bing" в приложение на JavaScript и HTML, требуется немного дополнить код. Добавьте следующий тег &lt;script> в HTML-код приложения: 

<div> </div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">script</span> <span style="color: rgb(255, 0, 0);">type</span><span style="color: rgb(0, 0, 255);">=&quot;text/javascript&quot;</span> <br />   <span style="color: rgb(255, 0, 0);">src</span><span style="color: rgb(0, 0, 255);">=&quot;ms-appx:///Bing.Maps.JavaScript//js/veapicore.js&quot;</span><span style="color: rgb(0, 0, 255);">&gt;</span><br />/script<span style="color: rgb(0, 0, 255);">&gt;</span><br /></pre>
  </div>
</blockquote>

<p>После этого необходимо создать тег &lt;div>, содержащий карту, и задать атрибут id для доступа к ней.</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">div</span> <span style="color: rgb(255, 0, 0);">id</span>=’<span style="color: rgb(255, 0, 0);">map-div</span>’<span style="color: rgb(0, 0, 255);">&gt;&lt;/</span><span style="color: rgb(128, 0, 0);">div</span><span style="color: rgb(0, 0, 255);">&gt;</span></pre>
  </div>
</blockquote>

<p>Затем необходимо инициализировать элемент управления map на HTML-странице. Вот код JavaScript, который это делает:</p>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 128, 0);">// Load the Microsoft.Maps.Map module and then call getMap when the </span><br /><span style="color: rgb(0, 128, 0);">// module has loaded.</span><br /><span style="color: rgb(0, 0, 255);">function</span> initMap() {<br />  Microsoft.Maps.loadModule(<span style="color: rgb(0, 96, 128);">'Microsoft.Maps.Map'</span>, <br />    { <br />      callback: getMap, <br />      culture: <span style="color: rgb(0, 96, 128);">&quot;en&quot;</span>, <br />      homeRegion: <span style="color: rgb(0, 96, 128);">&quot;US&quot;</span> <br />  });<br />}<br /><br /><span style="color: rgb(0, 128, 0);">// Get the div to contain the map from the interface of the app.</span><br /><span style="color: rgb(0, 0, 255);">function</span> getMap() {<br /><br />  <span style="color: rgb(0, 128, 0);">// Create a new instance of the Map class, passing in the app ID.</span><br />  <span style="color: rgb(0, 0, 255);">var</span> map = <span style="color: rgb(0, 0, 255);">new</span> Microsoft.Maps.Map(<br />    document.getElementById(mapDivId), <br />    { credentials: “Insert your credentials here” });<br /><br />  <span style="color: rgb(0, 128, 0);">// Set the initial zoom level and type of map.</span><br />  map.setView({<br />    mapTypeId: Microsoft.Maps.MapTypeId.road,<br />    zoom: 3<br />  });<br />}<br /></pre>
  </div>
</blockquote>

<ul>
  <li>Наконец, любое приложение, использующее данные о расположении, должно соблюдать установленные параметры разрешений, которые пользователь может изменить в любой момент. Приложение "Погода" использует данные о расположении, чтобы получить прогноз погоды для данной местности. Однако пользователь может в любой момент перейти к параметрам и отключить разрешения на определение расположения. Ваше приложение всегда должно учитывать такую возможность. Например, в такой ситуации приложение "Погода" отображает сообщение о том, что местоположение не может быть определено и вам необходимо изменить разрешения, чтобы приложение могло воспользоваться данными о расположении. Примеры обработки разрешений на определение расположения приведены в рекомендациях по взаимодействию с пользователем в <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/Hh465148%28v=win.10%29.aspx" target="_blank">руководстве для приложений, использующих данные о местоположении</a>. 

    <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0882.bing-weather_2FEEBCEF.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0882.bing_2D00_weather_5F00_2FEEBCEF.jpg"><img title="Приложение &quot;Погода Bing&quot;" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Приложение &quot;Погода Bing&quot; использует данные о расположении для получения прогноза погоды для текущего местоположения" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7356.bing-weather_thumb_084840C5.jpg" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7356.bing_2D00_weather_5F00_thumb_5F00_084840C5.jpg" width="600" height="450" /></a></li>
</ul>

<p> </p>

<p>Подробное описание использования пространства имен geolocation и пакета SDK для приложения "Карты Bing" <a></a><a>приведено в новых материалах — </a><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/jj850315.aspx" target="_blank">видеоролике, практических инструкциях</a> и <a href="http://code.msdn.microsoft.com/windowsapps/Simple-geolocation-with-7b385c3c" target="_blank">примере кода</a>, где рассматриваются этапы асинхронного получения данных о расположении и использование пакета SDK для приложения "Карты Bing" для визуального представления текущего местоположения. Из этих материалов вы узнаете о том, как включить возможность определения расположения, как асинхронно получать данные о расположении, отображать заданное местоположение на карте и изменять значок расположения в зависимости от точности получаемых данных. Дополнительную информацию можно найти в статье, посвященной <a href="http://msdn.microsoft.com/ru-ru/library/hh846481.aspx" target="_blank">использованию карт Bing в приложениях Магазина Windows</a> (возможно, на английском языке).</p>

<h2>Заключение</h2>

<p>Определение расположения в вашем приложении может оказаться крайне полезной и экономящей время функцией. Вы можете предоставлять пользователю более актуальную информацию в зависимости от его местонахождения. Предоставляет ли приложение список местных радиостанций, информацию о скидках в магазинах, сведения о ситуации на дорогах или прогноз погоды, возможность настройки этой информации с учетом местоположения может сделать ваше приложение еще полезнее и информативнее. А возможность автоматической работы этой функции без вмешательства пользователя экономит время и делает ваше приложение более привлекательным.</p>

<p>– Росс Хейзе (Ross Heise), старший разработчик контента, отдел контента для разработчиков для Windows</p>
<p>   Выражаем отдельную благодарность Йону Кэю (Jon Kay) и Эрику Шмидту (Eric Schmidt) за их помощь при создании этой статьи.</p>
<!-- Title: “Создание приложений, учитывающих местоположение пользователя, с помощью пространства имен geolocation и приложения "Карты Bing"” Tags: “Карты Bing, geolocation, Windows. Устройства. Geolocation, службы определения местоположения” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Новый дизайн Центра разработки для Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/73</link>
      <pubDate>Thu, 16 May 2013 09:51:00 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/05/16/73/</guid>
      <description><![CDATA[C момента запуска Центра разработки для Windows в октябре 2011 года мы активно взаимодействовали с...]]></description>
      <content:encoded><![CDATA[<div class="PostContent">
<p>C момента запуска <a href="http://msdn.microsoft.com/ru-ru/windows/default.aspx" target="_blank">Центра разработки для Windows</a> в октябре 2011 года мы активно взаимодействовали с разработчиками и дизайнерами из разных стран, чтобы понять, как лучше всего предоставлять рекомендации, советы и примеры разработчикам приложений. Миллионы посетителей и ваши отзывы позволяли нам определять, что работает хорошо, а что требует доработки.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0172.windows_dev_center_1EC86298.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0172.windows_5F00_dev_5F00_center_5F00_1EC86298.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Центр разработки для Windows" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0184.windows_dev_center_thumb_1DEFFCAE.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0184.windows_5F00_dev_5F00_center_5F00_thumb_5F00_1DEFFCAE.png" alt="Центр разработки для Windows" width="600" height="338" border="0" /></a></p>
<h2>Новые возможности</h2>
<p>Сейчас группа разработчиков Windows сконцентрировала свои усилия на формировании энергично развивающейся и эффективной экосистемы приложений. Эта задача имеет три компонента: отличные приложения, отличные экономические показатели и отличные возможности охвата. Новый центр разработки предоставляет разработчикам приложений, дизайнерам и организациям ресурсы, необходимые для успешной разработки отличных приложений и ведения коммерческой деятельности на базе Windows.</p>
<p>Для достижения этих целей Центр разработки был видоизменен следующим образом:</p>
<ol>
<li>Изменилась модель навигации, чтобы вы могли найти материалы именно по тому этапу жизненного цикла разработки, на котором сейчас находится ваше приложение.</li>
<li>В структуре сайта выделяются основные задачи, сценарии и новый контент.</li>
</ol>
<p>В дополнение к необходимым разработчикам материалам, примерам и скачиваемым файлам мы упросили доступ к ресурсам для дизайнеров и коммерческих организаций.</p>
<p>В зависимости от того, над чем вы работаете, можно перейти к одной из четырех областей: <a href="http://msdn.microsoft.com/ru-ru/windows/apps/br229512" target="_blank">приложение Магазина Windows</a>, <a href="http://msdn.microsoft.com/ru-ru/ie/" target="_blank">Internet Explorer</a>, <a href="http://msdn.microsoft.com/ru-ru/windows/desktop" target="_blank">рабочий стол Windows</a> и <a href="http://msdn.microsoft.com/ru-ru/windows/hardware" target="_blank">оборудование</a>. Для каждой из них предлагается новый интерфейс, соответствующий указанным выше пунктам. В этой статье мы подробно рассмотрим конкретные изменения, внесенные для приложений Магазина Windows.</p>
<h2>Подходящий контент для вашей роли</h2>
<p>Даже самый информативный веб-сайт не принесет никакой пользы, если вы не можете найти на нем нужную информацию. С учетом того, что Центр разработки содержит сотни тысяч разделов и тем, упорядочение контента и обеспечение возможности его найти становится критически важной задачей. С точки зрения разработки приложений Магазина Windows это означает более четкую структуризацию с учетом роли и сценария &mdash; от размещения всех материалов, необходимых для начала работы, в одном месте до более эффективной поддержки дизайнеров и предприятий. Ниже перечислены некоторые из основных нововведений.</p>
<h3>Разработчики</h3>
<p>Мы доработали и упростили материалы, необходимые вам для создания отличных приложений Магазина Windows. Когда вы откроете <a href="http://msdn.microsoft.com/ru-RU/windows/apps/" target="_blank">домашнюю страницу приложений Магазина Windows</a>, то увидите следующее:</p>
<ul>
<li>Первой отображается подборка наиболее важных задач и материалов, позволяющая быстро перейти к необходимому контенту. Отображается перечень локальных мероприятий для вашего региона, а также новых ресурсов, недавно добавленных на сайт.</li>
<li>Скачиваемые файлы, позволяющие приступить к написанию кода, все ресурсы, необходимые для начала работы, а также подробные рекомендации по публикации приложения в Магазине Windows.</li>
<li>Наиболее важные примеры кода выделены, а навигация по практическим руководствам упрощена и привязана к жизненному циклу разработки.</li>
<li>На сайте предлагаются <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211360.aspx" target="_blank">одноминутные видеоролики по разным аспектам разработки</a>, в сжатой форме рассказывающие о том, как добавить новые возможности в ваше приложение.</li>
</ul>
<h3>Дизайнеры</h3>
<p>Мы тщательно переработали <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh779072.aspx" target="_blank">раздел сайта, посвященный проектированию</a>, чтобы сделать его более удобным и информативным. Теперь стало проще находить нужные скачиваемые файлы и полезные ресурсы для проектирования, а советы и конкретные примеры позволят вам создать уникальный интерфейс для взаимодействия с пользователем в Windows. Все необходимое для создания привлекательного и выделяющегося из общей массы приложения всегда будет у вас под рукой благодаря удобному дизайну страниц с поддержкой управления касанием.</p>
<h3>Организации</h3>
<p>Магазин Windows предоставляет широкие бизнес-возможности, поскольку обладает лучшей по сравнению с конкурирующими платформами экономической моделью и гибкостью, позволяющими вам выстраивать бизнес согласно своим предпочтениям. Новый <a href="http://go.microsoft.com/fwlink/?LinkID=285998" target="_blank">раздел о рынке</a> на сайте содержит полезные советы по продвижению приложений на рынке, анализу данных телеметрии и прохождению сертификации приложений. Мы многое узнали о том, как упростить сертификацию, и переработали соответствующие материалы, чтобы процесс сертификации не вызывал у вас никаких трудностей.</p>
<p>Конечно, многие из совмещают сразу несколько ролей, и мы считаем, что новая структура сайта позволит учесть все это. Являетесь ли вы просто увлеченным человеком, работником дизайнерского агентства или сотрудником крупнейшей компании по разработке корпоративного программного обеспечения, новая организация материала на сайте поможет вам в ваших творческих и коммерческих свершениях вместе с Windows.</p>
<h2>Впереди еще много интересного, поэтому нам нужны ваши отзывы</h2>
<p>Учитывая, что до начала конференции <a href="http://www.buildwindows.com">BUILD 2013</a> осталось чуть больше одного месяца, предстоит еще многое обсудить. Мы упорно работаем над созданием нового контента, рассказывающего о том, что будет представлено на конференции в этом году. Кроме данного блога, для получения актуальной информации можно использовать следующие источники: <a href="https://twitter.com/#!/windevs" target="_blank">@windevs</a> в Twitter и подписку на <a href="http://www.windowsstore.com/newsletter-signup" target="_blank">информационный бюллетень Магазина Windows</a>.</p>
<p>Параллельно с публикацией новых материалов по разработке, проектированию и маркетингу приложений Магазина Windows мы хотим улучшать опыт работы с Центром разработки! Чтобы вам было проще делиться своими замечаниями, мы предусмотрели два новых варианта обратной связи, доступных в нижней части каждой страницы. Оставляйте свои отзывы &mdash; мы внимательно изучаем их и всегда стремимся сделать вашу работу максимально комфортной.</p>
<p>&nbsp;</p>
<p>Кейт Бойд (Keith Boyd), руководитель по публикации контента, отдел контента для разработчиков для Windows</p>
<!-- Title: “Новый дизайн Центра разработки для Windows” Tags: “центр разработки, информация для разработчиков, создание приложений, приложения Магазина Windows, сборка, Центр разработки для Windows” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Предоставление контента в общий доступ целевому приложению</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/83</link>
      <pubDate>Wed, 15 May 2013 09:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/05/15/83/</guid>
      <description><![CDATA[В статье Предоставление контента в общий доступ из приложения мы описали, как делиться контентом...]]></description>
      <content:encoded><![CDATA[<div class="PostContent">
<p>В статье <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/12/21/10380195.aspx" target="_blank">Предоставление контента в общий доступ из приложения</a> мы описали, как делиться контентом из приложения <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/07/18/cr-233-ation-d-applications-de-style-metro-qui-sortent-du-lot.aspx" target="_blank">Ужин с друзьями</a> с несколькими целевым приложениям, позволяющими реализовать эффективные комплексные сценарии. Приложения в Windows 8 предоставляют интересный контент, которым ваши клиенты захотят <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465251.aspx" target="_blank">поделиться</a> с друзьями или другими приложениями. Благодаря удобному и правильно спроектированному получателю данных ваше приложение может стать центром социального и сетевого взаимодействия для ваших клиентов.</p>
<p>В данной статье мы рассмотрим, как вы можете использовать контракт получателя данных для своих приложений, особенно тех, которые похожи на "Ужин с друзьями". С помощью данного контракта ваше приложение может <em>принимать контент</em> из других приложений и использовать его для улучшения своей работы. Мы хотим помочь вам добиться того, чтобы ваше приложение стало лучшим в своей категории!</p>
<p>Целевое приложение создается с использованием <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/03/30/windows-8-activating-contracts.aspx" target="_blank">контракта</a> получателя данных и предназначено для ускорения и упрощения процедуры общего доступа. Не каждое приложение в Windows будет получателем данных, но если ваше приложение может публиковать, преобразовывать, хранить получаемый из другого приложения контент или каким-либо образом повышать его ценность, следует задуматься о тех преимуществах, которые дает создание получателя данных.</p>
<ul>
<li>Ваше приложение всегда будет отображаться в списке целевых приложений. Оно всегда актуально и находится на связи с другими приложениями, которые могут предоставлять необходимые вам данные.</li>
<li>Контракт отправки данных создает связь между вашим приложением и исходным приложением без необходимости их взаимной интеграции.</li>
<li>Поскольку чудо-кнопка "Общий доступ" всегда присутствует и доступна в операционной системе, она обеспечивает целевому приложению представление в операционной системе, выходящее за рамки самого приложения. Все это может привлечь к вашему приложению еще больше клиентов!</li>
</ul>
<h2>Получение общего контента</h2>
<p>Давайте рассмотрим несколько примеров того, как обеспечить удобную работу с помощью целевого приложения для обмена данными.</p>
<p>Возможно, вы уже знакомы с приложениями "Почта" и "Люди" в Windows 8. Приложение "Почта" предлагает простой персонализированный интерфейс получателя данных для приема контента и его совместного использованиями с одним или несколькими друзьями. Приложение "Люди" позволяет вам предоставлять контент для общего доступа более широкому кругу пользователей в социальных сетях. Вы можете не только делиться контентом с другими людьми, но и воспользоваться обменом данными между приложениями. Приложения, предназначенные для повышения производительности труда, такие как SkyDrive, могут принимать файлы из любого источника в операционной системе Windows и сохранять их в облаке; приложения для ведения заметок могут принимать текст, ссылки и, возможно, данные в разных форматах и архивировать их для использования в дальнейшем. Все этого открывает широкие возможности и простор для творчества.</p>
<p>На следующих двух рисунках показан процесс обмена данными, где фотография из приложения "Фотографии" передается в PuzzleTouch &mdash; игру, превращающую изображение в мозаичную головоломку.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8637.puzzletouch1_6E4332DA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8637.puzzletouch1_5F00_6E4332DA.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Исходное приложение слева; список отфильтрованных целевых приложений, которые могут принять фотографии, на панели общего доступа справа. " src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1307.puzzletouch1_thumb_2681A9F3.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1307.puzzletouch1_5F00_thumb_5F00_2681A9F3.png" alt="Исходное приложение слева; список отфильтрованных целевых приложений, которые могут принять фотографии, на панели общего доступа справа. " width="700" height="394" border="0" /></a></p>
<p align="center"><em>Рисунок 1. Исходное приложение слева; список отфильтрованных целевых приложений, которые могут принять фотографии, на панели общего доступа справа. <br />Приложение PuzzleTouch является одним из получателей данных, которые могут принять изображение из приложения "Фотографии". </em></p>
<p align="left"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6661.puzzletouch2_463083BB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6661.puzzletouch2_5F00_463083BB.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Расположенное справа целевое призрачное приложение позволяет пользователю выбрать тип создаваемой головоломки" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/2474.puzzletouch2_thumb_65DF5D83.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/2474.puzzletouch2_5F00_thumb_5F00_65DF5D83.png" alt="Расположенное справа целевое призрачное приложение позволяет пользователю выбрать тип создаваемой головоломки" width="700" height="394" border="0" /></a></p>
<p align="center"><em>Рисунок 2. Расположенное справа целевое призрачное приложение позволяет пользователю выбрать тип <br />создаваемой головоломки. Когда пользователь возвращается в приложение, он получает готовую головоломку. </em></p>
<h2>Что такое целевое приложение для обмена данными?</h2>
<p>Возможности "сквозного" общего доступа в Windows состоят из двух компонентов. Есть исходное приложение, делающее свой контент доступным в различных форматах операционной системе Windows. Кроме того, есть также целевое приложение для обмена данными, которое регистрируется для распознавания определенных форматов и является получателем контента, предоставляемого в общий доступ. Контракт отправки данных обеспечивает взаимодействие приложений, являющихся источником и получателем данных.</p>
<p>Когда вы обдумываете организацию общего доступа в своем приложении, рассмотрите возможность отображения целевого приложения для обмена данными в размещаемом окне общего доступа. Спроектируйте интерфейс таким образом, чтобы пользователь мог быстро просмотреть свой контент и подтвердить общий доступ. В данном примере приведено представление целевого приложения для обмена данными "Почта", позволяющее пользователю быстро передать ссылку из браузера одному из своих почтовых контактов.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8561.Share-Target-Image_3ED44139.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8561.Share_2D00_Target_2D00_Image_5F00_3ED44139.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Изображение получателя данных" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6011.Share-Target-Image_thumb_4FD86F1C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6011.Share_2D00_Target_2D00_Image_5F00_thumb_5F00_4FD86F1C.png" alt="Изображение получателя данных" width="700" height="435" border="0" /></a></p>
<p align="center"><em>Рисунок 3. Передача ссылки из приложения "Фотографии" с использованием приложения "Почта" в качестве получателя данных</em></p>
<h2>Сценарии для приложения "Ужин с друзьями"</h2>
<p>А теперь давайте рассмотрим, благодаря чему приложение <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/07/18/cr-233-ation-d-applications-de-style-metro-qui-sortent-du-lot.aspx" target="_blank">Ужин с друзьями</a> удобно использовать в качестве целевого приложения для обмена данными. Если вы уже знакомы с этим приложением, то знаете, что пользователь может выполнить в нем две основные задачи &mdash; <em>создание плана</em> и <em>добавление ресторана в свой список предпочтений</em>. Конечно, доступны и другие действия, такие как написание обзора, публикация комментария, просмотр списков предпочтений своих друзей и тому подобное, но эти операции имеют смысл только в контексте основного приложения. Давайте проведем для этих двух основных сценариев быструю проверку работоспособности, чтобы узнать, обеспечивается ли их эффективное выполнение с использованием целевого приложения "Ужин с друзьями".</p>
<h3>Создание плана на вечер</h3>
<p>Хотя эта задача и является ключевым сценарием основного приложения, она не является оптимальной для использования получателя данных. И вот почему: работа с получателем данных должна осуществляться легко и быстро. Создание плана представляет собой значительно более комплексную задачу &mdash; пользователь хочет узнать, какие другие рестораны хотели бы посетить его друзья, сравнить несколько ресторанов из их списка предпочтений, просмотреть оценки и т. д. Поскольку для планирования требуется использовать сведения, оптимальным образом представленные в окне основного приложения, внедрение данной функциональной возможности в целевое приложение для обмена данными нельзя назвать привлекательным решением.</p>
<p>&nbsp;</p>
<h3>Добавление в список предпочтений</h3>
<p>Этот сценарий является хорошим примером короткой и целенаправленной задачи в получателе данных. Вот некоторые особенности его реализации в этом приложении:<strong></strong></p>
<ul>
<li>Люди находят рестораны в других приложениях, например в приложениях для планирования поездок, путеводителях по городу, кулинарных блогах и т. д. Приложение "Ужин с друзьями" отлично подходит для получения контента и вывода сводных сведений о ресторанах в разделе "Мои пожелания".</li>
<li>Представление целевого приложения предназначено для того, чтобы пользователь мог быстро выполнить действие, находясь в контексте другого приложения. Таким образом, добавление ресторана в список предпочтений отлично подходит для использования в получателе данных.</li>
<li>Хотя пользователь может переключиться на другое приложение, повторить поиск ресторана и добавить найденный ресторан в свой список предпочтений, значительно проще коснуться чудо-кнопки "Общий доступ".</li>
</ul>
<p>Получается, что список предпочтений в приложении "Ужин с друзьями" отлично подходит для проектирования и создания целевого приложения для обмена данными. Вот комплексный сценарий того, что мы хотим сделать:</p>
<p>Просматривая приложение, показывающее местные кафе-фургоны, я нахожу кафе-фургон с хорошими рекомендациями. Я хочу добавить этот кафе-фургон из текущего приложения в раздел "Мои предпочтения" приложения "Ужин с друзьями" для последующего использования при планировании.</p>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7658.contoso_truck_6C263411.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7658.contoso_5F00_truck_5F00_6C263411.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Просмотр приложения, показывающего местные кафе-фургоны и рекомендующего интересные места для посещения" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3022.contoso_truck_thumb_4B9EF45F.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3022.contoso_5F00_truck_5F00_thumb_5F00_4B9EF45F.png" alt="Просмотр приложения, показывающего местные кафе-фургоны и рекомендующего интересные места для посещения" width="700" height="394" border="0" /></a><em>Рисунок 4. Просмотр приложения, показывающего местные кафе-фургоны и рекомендующего интересные места для посещения</em></p>
<p>На этом изображении приведено представление целевого приложения для обмена данными, которое мы хотим использовать:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3835.contoso_truck2_565C4BB4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3835.contoso_5F00_truck2_5F00_565C4BB4.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Представление целевого приложения для обмена данными" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/8637.contoso_truck2_thumb_760B257C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/8637.contoso_5F00_truck2_5F00_thumb_5F00_760B257C.png" alt="Представление целевого приложения для обмена данными" width="700" height="394" border="0" /></a></p>
<p align="center"><em>Рисунок 5. Представление целевого приложения для обмена данными</em></p>
<p>Осуществляя обмен данными в представлении целевого приложения, пользователи могут управлять ресторанами в приложении "Ужин с друзьями" без выхода из контекста текущего иммерсивного приложения.</p>
<h2>Реализация получателя данных</h2>
<p>Теперь, когда мы познакомились с несколькими ситуациями, в которых стоит реализовать получатель данных, давайте рассмотрим, как это можно сделать. Во-первых, определите, данные в каких форматах может принимать ваше приложение.</p>
<h3>Какие форматы данных следует поддерживать?</h3>
<p>С помощью контракта отправки данных вы можете реализовать поддержку данных в стандартных форматах (текст, URI, HTML, растровое изображение, файлы и т. п.), а также в пользовательских форматах данных, приведенных на сайте <a href="http://schema.org" target="_blank">http://schema.org</a> . Операционная система Windows отбирает целевые приложения по поддерживаемым ими форматам данных, чтобы отобразить отфильтрованный список целевых приложений на панели общего доступа. Ваше приложение должно поддерживать те форматы данных, которые нужны при работе с ним. Например, если ваше приложение посвящено просмотру фотографий, поддержка текстовых форматов может оказаться лишней. Если вы объявляете поддержку нескольких форматов данных, определите, какой из них позволяет наилучшим образом представить данные, предоставляемые в общий доступ, чтобы вы могли выбрать этот формат из пакета данных первым.</p>
<p>Поскольку приложение "Ужин с друзьями" реализует режим получателя данных, позволяющий пользователям отправлять в это приложение данные о ресторанах, мы воспользуемся форматом данных <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a>, приведенным на сайте <a href="http://schema.org" target="_blank">http://schema.org</a>. Приложение "Ужин с друзьями" может воспользоваться контрактом получателя данных, чтобы зарегистрироваться для получения данных в этом формате. Затем, используя данные из полученного пакета, оно может обеспечить удобный опыт работы в своем представлении целевого приложения, позволяющем пользователю добавить ресторан в свой список предпочтений.</p>
<p>В то время как некоторые исходные приложения могут специально использовать формат данных <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a> для предоставления контента в общий доступ, другие исходные приложения могут представлять аналогичную информацию в других форматах, таких как <a href="http://schema.org/Place" target="_blank">Place</a>, <a href="http://schema.org/LocalBusiness" target="_blank">LocalBusiness</a> и <a href="http://schema.org/FoodEstablishment" target="_blank">FoodEstablishment</a>, приведенных на сайте <a href="http://schema.org/" target="_blank">schema.org</a>. Таким образом, в контракте отправки данных приложение "Ужин с друзьями" может поддерживать прием данных в нескольких форматах, чтобы охватить больше исходных приложений.</p>
<p>Приложение "Ужин с друзьями" поддерживает следующие форматы в объявлениях получателя данных в манифесте приложения:</p>
<ul>
<li><span style="text-decoration: underline;"><a href="http://schema.org/Restaurant" target="_blank">Restaurant</a></span>;</li>
<li><span style="text-decoration: underline;"><a href="http://schema.org/Place" target="_blank">Place</a></span>;</li>
<li><span style="text-decoration: underline;"><a href="http://schema.org/LocalBusiness" target="_blank">LocalBusiness</a></span>;</li>
<li><span style="text-decoration: underline;"><a href="http://schema.org/FoodEstablishment" target="_blank">FoodEstablishment</a></span>.</li>
</ul>
<p>&nbsp;</p>
<p>Для краткости в этой статье мы уделяем основное внимание типу данных <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a>, однако изложенные здесь понятия применимы и к другим типам данных.</p>
<h3>Какие форматы данных и сценарии следует исключить?</h3>
<p>Приложение "Ужин с друзьями" поддерживает добавление ресторана в список предпочтений пользователя только в том случае, когда полученная информация соответствует ресторану, о котором приложению уже известно. Это сделано намеренно для предотвращения дублирования ресторанов в приложении.</p>
<p>Мы не поддерживаем стандартные типы данных, так как большая часть текста, файлов, фотографий, URI или HTML, предоставляемых для общего доступа из исходных приложений, не будет сопоставлена с каким-либо рестораном или местным предприятием. Например, если бы приложение "Ужин с друзьями" поддерживало прием текста, оно бы отображалось в списке целевых приложений для исходного приложения, посвященного ведению заметок. В этом случае приложению "Ужин с друзьями" потребовалось бы отобразить сообщение об ошибке, информирующее пользователя о том, почему оно не работает с данным исходным приложением. По сути, именно форматы данных соединяют исходное приложение, предлагающее определенную информацию, с целевым приложением. Если форматы данных не совпадают, обмен данными не происходит.</p>
<p>Убедитесь, что вы учли все форматы данных, необходимые для работы с приложением, и исключили те форматы, которые ухудшают опыт обмена данными.</p>
<h3>Поддержка контракта получателя данных</h3>
<p>Чтобы обеспечить поддержку форматов данных, объявите их для своего приложения в конструкторе манифестов Visual Studio. Вот что происходит, когда пользователь выбирает ваше приложение в качестве целевого для операций общего доступа:</p>
<ol>
<li>В окне получателя данных поверх исходного приложения запускается новый экземпляр приложения.</li>
<li>Возникает событие <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.activation.sharetargetactivatedeventargs.aspx" target="_blank">активации получателя данных</a>, и в результате ваше приложение получает объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><strong></strong>.</li>
<li>Ваше приложение может извлечь данные, предоставленные пользователем для общего доступа, из этого объекта.</li>
<li>Эти данные можно использовать для отображения представления целевого приложения и завершения процедуры обмена данными.</li>
</ol>
<p>Подробнее о реализации такого взаимодействия с пользователем рассказано в <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465255.aspx"><span style="text-decoration: underline;">кратком руководстве</span></a>, посвященном <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465255.aspx" target="_blank">получению общего контента</a>.</p>
<p>Кроме того, Visual Studio поддерживает шаблон для получателей данных. Щелкните свой проект правой кнопкой мыши, выберите пункт <strong>Добавить элемент</strong>, щелкните <strong>Добавить новый элемент</strong> и выберите элемент <strong>Контракт получателя данных</strong> в списке, чтобы добавить код для поддержки данного контракта. В <a href="http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782" target="_blank">примере кода для получателя данных</a> показано, как именно следует принимать контент, предоставленный в общий доступ.</p>
<h2>Разработка настроенного представления целевого приложения</h2>
<p>Когда пользователь выбирает целевое приложение в списке на панели общего доступа, Windows запускает это приложение в представлении получателя данных. Это специальное представление, размещаемое на панели общего доступа и отличающееся от основного представления приложения. Подробнее о таких встроенных представлениях и их активации рассказано в статье <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/03/30/windows-8-activating-contracts.aspx" target="_blank">Активация контрактов Windows 8 в вашем приложении</a>. Представление получателя данных помогает выполнить инициированную пользователем операцию предоставления данных в общий доступ. В этом представлении пользователи должны иметь возможность быстро просмотреть контент, выполнить простые действия и подтвердить обмен данными.</p>
<p>Прежде чем рассмотреть структуру целевого приложения для приложения "Ужин с друзьями", давайте обратимся к целевому приложению, с которым вы, возможно, уже знакомы. На следующих изображениях показано представление получателя данных для приложения "Почта" и полное представление того же приложения вWindows 8.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1307.target-app_4AC68E75.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1307.target_2D00_app_5F00_4AC68E75.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Передача данных из приложения &quot;Фотографии&quot; в целевое приложение &quot;Почта&quot; справа" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0724.target-app_thumb_5583E5CA.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0724.target_2D00_app_5F00_thumb_5F00_5583E5CA.png" alt="Передача данных из приложения &quot;Фотографии&quot; в целевое приложение &quot;Почта&quot; справа" width="700" height="438" border="0" /></a></p>
<p align="center"><em>Рисунок 6. Передача данных из приложения "Фотографии" в целевое приложение "Почта" справа</em></p>
<p align="left"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1385.mail_154DCC50.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1385.mail_5F00_154DCC50.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Составление нового сообщения в представлении основного приложения &quot;Почта&quot;" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/2055.mail_thumb_510D6503.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/2055.mail_5F00_thumb_5F00_510D6503.png" alt="Составление нового сообщения в представлении основного приложения &quot;Почта&quot;" width="700" height="438" border="0" /></a></p>
<p align="center"><em>Рисунок 7. Составление нового сообщения в представлении основного приложения "Почта"</em></p>
<p>Обратите внимание на то, что представление получателя данных у приложения "Почта" проще его полного представления. Оно обеспечивает понятное и легко воспринимаемое представление контента, которым пользователь собирается поделиться, в виде эскиза и соответствующего текста и HTML-кода. В нем есть строка <strong>Кому</strong> для добавления получателей, область для ввода короткого текстового сообщения и простое средство подтверждения отправки в виде кнопки <strong>Отправить</strong>.</p>
<p>Несмотря на упрощенный внешний вид, в представлении получателя данных легко узнать внешний вид приложения "Почта", что укрепляет уверенность пользователя в том, что общий контент будет отправлен по назначению.</p>
<h2>Использование приложения "Ужин с друзьями" в качестве целевого приложения для обмена данными</h2>
<p>Теперь, когда у вас сложилось общее представление о структуре представления целевого приложения, давайте рассмотрим, как создать такое представление приложения "Ужин с друзьями", которое помогает пользователям добавлять рестораны в список предпочтений.</p>
<p>Когда приложение "Ужин с друзьями" получает пакет с данными в формате <a href="http://schema.org/Restaurant">Restaurant</a> из исходного приложения, оно может использовать сведения из формата <a href="http://schema.org/Restaurant">Restaurant</a>, чтобы определить, какой ресторан из имеющейся базы данных соответствует полученному пакету данных. Затем приложение может осуществить предварительный просмотр этого ресторана в представлении получателя данных. Это позволяет убедиться в целостности контента, предлагаемого для общего доступа.</p>
<p>На этом изображении приведено представление получателя данных для приложения "Ужин с друзьями":</p>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3857.contoso_truck3_0305058E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3857.contoso_5F00_truck3_5F00_0305058E.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Представление получателя данных для приложения &quot;Ужин с друзьями&quot;" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5584.contoso_truck3_thumb_1B94A2DE.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5584.contoso_5F00_truck3_5F00_thumb_5F00_1B94A2DE.png" alt="Представление получателя данных для приложения &quot;Ужин с друзьями&quot;" width="700" height="394" border="0" /></a><em>Рисунок 8. Представление получателя данных для приложения "Ужин с друзьями"</em></p>
<p>Как вы сами можете убедиться, это простое представление приложения "Ужин с друзьями", созданное специально, чтобы делиться, для целевого приложения. Оно обеспечивает предварительный просмотр информации о ресторане, которой пользователь собирается поделиться, и содержит простую кнопку <strong>Добавить в список предпочтений</strong>, поясняющую, где в основном приложении будет использоваться общий контент. Когда пользователь нажимает эту кнопку или касается ее, он подтверждает операцию предоставления в общий доступ. Предусмотрев обязательное участие пользователя, мы помогаем предотвратить случайную отправку данных и повышаем надежность всего процесса предоставления контента в общий доступ.</p>
<p>Если приложение "Ужин с друзьями" находит несколько ресторанов, соответствующих информации из пакета данных, оно использует представление получателя данных для отображения вариантов, чтобы пользователь мог выбрать один из них.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5582.contoso_truck4_70500BD6.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5582.contoso_5F00_truck4_5F00_70500BD6.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="В представлении получателя данных отображаются варианты, чтобы пользователи могли выбрать элементы, которыми надо поделиться" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/6175.contoso_truck4_thumb_6FE3D8E1.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/6175.contoso_5F00_truck4_5F00_thumb_5F00_6FE3D8E1.png" alt="В представлении получателя данных отображаются варианты, чтобы пользователи могли выбрать элементы, которыми надо поделиться" width="700" height="394" border="0" /></a></p>
<p align="center"><em>Рисунок 9. В представлении получателя данных отображаются варианты, чтобы пользователи могли выбрать элементы, которыми надо поделиться</em></p>
<p>&nbsp;</p>
<p>Если на основании полученного пакета данных приложение не может точно определить ресторан или допустимый набор вариантов, используйте представление целевого приложения для отображения соответствующего сообщения.</p>
<h2>Создание объекта QuickLink</h2>
<p><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.quicklink.aspx" target="_blank">QuickLink</a> &mdash; это реализация API-интерфейса Share, позволяющая быстро делиться контентом с известными адресатами в целевом приложении. QuickLink выступает в качестве настраиваемой ссылки на целевое представление, предлагая выполнение определенных действий. Когда Windows выполняет фильтрацию списка доступных пользователю целевых приложений, список объектов QuickLink отображается в верхней части панели общего доступа в качестве списка доступных назначений. Эти известные адресаты или пользовательские действия могут включать в себя места или людей, с которыми часто осуществляется обмен данными посредством этого целевого приложения. Например, приложение "Почта" возвращает объекты QuickLink для контактов, которым ранее уже отправлялись сообщения. Аналогичным образом вы можете добавить объекты QuickLink для папок, групп, записных книжек и списков воспроизведения, которые вы часто отправляете для общего доступа в целевое приложение.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5001.quicklink_2FADBF67.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5001.quicklink_5F00_2FADBF67.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="На панели общего доступа показан объект QuickLink, предоставленный целевым приложением &quot;Почта&quot; для контактов, которым уже отправлялись сообщения с помощью этого целевого приложения" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1374.quicklink_thumb_334BDA44.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1374.quicklink_5F00_thumb_5F00_334BDA44.png" alt="На панели общего доступа показан объект QuickLink, предоставленный целевым приложением &quot;Почта&quot; для контактов, которым уже отправлялись сообщения с помощью этого целевого приложения " width="700" height="438" border="0" /></a></p>
<p align="center"><em>Рисунок 10. На панели общего доступа показан объект QuickLink, предоставленный целевым приложением "Почта" для контактов, <br />которым уже отправлялись сообщения с помощью этого целевого приложения</em></p>
<p>Целевое приложение может предоставить объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.quicklink.aspx" target="_blank">QuickLink</a>, вызвав метод <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportcompleted.aspx" target="_blank">reportCompleted</a><strong></strong><strong></strong>объекта <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><strong></strong><strong></strong>. Объект QuickLink должен иметь заголовок, значок и идентификатор. Заголовок (например, "Сообщение для мамы") и значок отображаются, когда пользователь касается чудо-кнопки "Общий доступ". Идентификатор используется приложением для доступа к любой пользовательской информации, например адресу электронной почты, расположению папки и т. п. Подробнее об этом средстве рассказано в статье, посвященной <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh758299.aspx" target="_blank">созданию объекта QuickLink</a>.&nbsp;</p>
<p>Примечание. Объекты QuickLink удобно использовать, когда приложение поддерживает выполнение нескольких действий из получателя данных. Поскольку приложение "Ужин с друзьями" поддерживает в получателе данных только одно действие &mdash; <strong>Добавить в список предпочтений</strong>, объекты QuickLink в нем не используются.</p>
<h2>Расширенный обмен данными и отчеты об ошибках</h2>
<p>Иногда исходные приложения отправляют в общий доступ большие блоки данных, например фотографии, видео или файлы, что приводит к затягиванию передачи данных. Операции общего доступа такого типа называются <em>расширенным обменом данными</em>, при котором целевому приложению может потребоваться больше времени на прием и обработку данных.</p>
<p>Поскольку делиться информацией необходимо быстро и плавно, а представление получателя данных с упрощенной структурой размещается поверх основного приложения, пользователи могут вернуться в основное приложение из представления получателя данных. Поэтому целевые приложения не должны зависеть от выполнения пользователем действий в представлении получателя данных после начала процесса обмена данными или ожидать выполнения таких действий. Целевые приложения могут использовать объект <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br205977.aspx" target="_blank">ShareOperation</a><strong></strong> и его методы, чтобы уведомить Windows о том, что приложение обрабатывает данные.</p>
<ul>
<li><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportstarted.aspx" target="_blank">reportStarted</a></strong> &mdash; вызовите этот метод, чтобы уведомить Windows о том, что приложение начало извлекать данные из объекта DataPackage исходного приложения.</li>
<li><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportdataretrieved.aspx" target="_blank">reportDataRetrieved</a></strong><strong></strong>&mdash; вызовите этот метод, чтобы уведомить Windows о том, что приложение закончило делиться данными.</li>
<li><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.datatransfer.sharetarget.shareoperation.reportcompleted.aspx" target="_blank">reportCompleted</a></strong><strong><span style="text-decoration: underline;"> &mdash; </span></strong>вызовите этот метод, чтобы уведомить Windows о том, что приложение закончило операцию общего доступа.<strong></strong><strong></strong></li>
</ul>
<p>Когда ваше приложение обрабатывает данные для расширенного обмена, выведите в представлении получателя данных индикатор хода выполнения. Он показывает пользователю, что его запрос принят, и позволяет отслеживать ход выполнения операции по предоставлению данных в общий доступ. Подробнее элементы управления ходом выполнения в Windows 8 рассматриваются в <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465487.aspx" target="_blank">кратком руководстве по добавлению элементов управления ходом выполнения</a>.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0702.progress-bar_52FAB40C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0702.progress_2D00_bar_5F00_52FAB40C.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="индикатор выполнения" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3438.progress-bar_thumb_40B1ED4A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3438.progress_2D00_bar_5F00_thumb_5F00_40B1ED4A.png" alt="индикатор выполнения" width="700" height="438" border="0" /></a></p>
<p align="center"><em>Рисунок 11. Представление получателя данных приложения "Почта" показывает индикатор хода выполнения расширенного обмена данными, например при отправке больших вложений</em></p>
<p>Если во время передачи данных возникают проблемы и целевому приложению приходится завершить операцию общего доступа, вы можете вызвать <strong><span style="text-decoration: underline;">reportError</span></strong>, чтобы отправить сообщение об ошибке операционной системе Windows. Пользователь увидит это сообщение при проверке состояния операции обмена данными на панели общего доступа. После регистрации ошибки приложение закрывается, а операция обмена данными завершается. Для отправки контента в ваше приложение пользователю потребуется начать процедуру с начала.</p>
<p>Если в примере с получателем данных "Ужин с друзьями" приложению не удается найти в своей базе данных ресторан, соответствующий предоставленному в общий доступ из исходного приложения в формате <a href="http://schema.org/Restaurant" target="_blank">Restaurant</a>, приложение должно сообщить об ошибке.</p>
<h2>Подведем итоги!</h2>
<p>Совместное использование контента приложениями открывает широкие возможности для приложений, являющихся получателями данных. Если ваше приложение может принимать общий контент, оно приносит пользу даже тогда, когда пользователи заняты совершенно другим делом. Мы надеемся, что теперь вы лучше понимаете принципы проектирования, а также типы данных, классы и свойства, которые можно использовать для создания отличного получателя данных. Мы будем с радостью наблюдать, как ваши приложения будут преобразовывать общий контент и предоставлять пользователям более широкие и интересные возможности.</p>
<p>Если вы хотите больше узнать об общем доступе, ознакомьтесь со статьей об <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh464923.aspx" target="_blank">общем доступе к данным и обмене данными</a> и <a href="http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782" target="_blank">примером целевого приложения для обмена контентом</a>, которые помогут вам на начальном этапе.</p>
<p>Ишита Капур (Ishita Kapur)</p>
<p>Руководитель программы</p>
<p>Рабочая группа по взаимодействию с пользователями Windows</p>
<!-- Title: “Предоставление контента в общий доступ целевому приложению” Tags: “общий доступ к контенту в приложениях, целевые приложения, общий контент, получатель данных, предоставление контента в общий доступ целевым приложениям” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Разработка современного приложения с использованием NFC</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/93</link>
      <pubDate>Wed, 24 Apr 2013 15:41:35 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/04/24/93/</guid>
      <description><![CDATA[Радиочастотная связь ближнего действия (NFC) — это набирающая популярность технология беспроводной...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"> <p>Радиочастотная связь ближнего действия (NFC) — это набирающая популярность технология беспроводной связи малого радиуса действия. Требуемое расстояние составляет 2 сантиметра, поэтому люди могут соприкасаться своими устройствами для отправки и приема контента. При этом вы можете быстро выбрать нужный объект или человека. Такой способ не только быстр, но и прост в освоении. Не нужно читать руководство — достаточно один раз увидеть все своими глазами.</p>  <p>Например, представьте ситуацию, когда вы просматриваете фотографии вместе с подругой и она хочет получить некоторые из них. Благодаря технологии NFC вам достаточно прикоснуться устройством к ее компьютеру, чтобы начать отправку фотографий. Слишком просто? Возможно, но главная идея и заключается именно в простоте обмена контентом между устройствами.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/1732.NFC-image_04E645BB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/1732.NFC_2D00_image_5F00_04E645BB.png"><img title="&#39;На изображении показан динамик Nokia 360, обменивающийся с устройством Windows Phone информацией о связывании по каналу Bluetooth" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="&#39;На изображении показан динамик Nokia 360, обменивающийся с устройством Windows Phone информацией о связывании по каналу Bluetooth" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3566.NFC-image_thumb_38420917.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3566.NFC_2D00_image_5F00_thumb_5F00_38420917.png" width="400" height="348" /></a></p>  <p align="center">Рисунок 1. На изображении показан динамик Nokia 360, обменивающийся с устройством    <br />Windows Phone информацией о связывании по каналу Bluetooth</p>  <p>Аналогично Bluetooth и Wi-Fi технология NFC представляет собой стандартный протокол беспроводной связи, определенный ассоциацией <a href="http://www.nfc-forum.org/home/" target="_blank">NFC Forum</a><u></u>. <u></u>Ваш компьютер должен быть оснащен радиопередатчиком NFC. Множество компьютеров с Windows 8 уже имеют встроенный радиопередатчик NFC. Если ваш компьютер еще не оборудован таким радиопередатчиком, вы можете приобрести аппаратные ключи NFC, подключаемые к компьютеру.</p>  <p>NFC предоставляет несколько замечательных возможностей. С помощью касания люди могут отправить фотографии, открыть меню и заказать блюдо в ресторане или даже выполнить связывание с устройством Bluetooth. Эти сценарии существенно отличаются друг от друга, однако их объединяет взаимодействие с помощью касания. NFC используется в различных устройствах, таких как компьютеры, телефоны, динамики, гарнитуры, беспроводные экраны и т. д., чтобы сделать соединение устройств простым и интуитивно понятным. Кроме того, NFC использует метки RFID — это дешевые и легкие пассивные антенны, которые могут содержать довольно большой объем данных и размещаться практически где угодно, чаще всего их помещают на плакаты и афиши. Например, для покупки билета в кинотеатр достаточно коснуться афиши фильма! Мы рассмотрим простейший пример с касанием метки NFC, чтобы продемонстрировать основные принципы API NFC.</p>  <p>Но сначала давайте подробнее разберемся с касанием устройствами.</p>  <h2>Определение термина "касание"</h2>  <p>Выполняете ли вы касание для связывания с мышью Bluetooth или для обмена фотографиями, важно соприкоснуться устройствами правильно. И хотя сама по себе идея касание хорошо знакома и понятна пользователям, касание компьютером другого устройства для большинства людей будет в новинку. Ниже приведены рекомендации по касанию, позволяющие пользователям определить следующее:</p>  <ol>   <li>     <div align="center"><b>Место для соприкосновения устройств</b> — это место определяется с помощью сенсорной метки, также называемой визуальной меткой "Поднести и сделать", обозначающей место расположения антенны NFC. В зависимости от модели для касания используются разные части компьютера. Например, на планшете это может быть задняя панель, а на универсальном компьютере — передняя. Вот как выглядит метка на любом компьютере с Windows 8 с поддержкой NFC:         <br /></div>     <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0830.NFC-logo_66E85720.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0830.NFC_2D00_logo_5F00_66E85720.png"><img title="Визуальная метка &quot;Поднести и сделать&quot;" style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" border="0" alt="Визуальная метка &quot;Поднести и сделать&quot;" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5611.NFC-logo_thumb_3FAE0DEB.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5611.NFC_2D00_logo_5F00_thumb_5F00_3FAE0DEB.png" width="200" height="147" /></a>      <p align="center">Рисунок 2. Визуальная метка "Поднести и сделать"</p>   </li>    <li><b>Взаимодействие устройств друг с другом</b> — во время касания пользователи должны быть уверены, что нужная операция выполняется, даже если они не могут увидеть передаваемые данные. Поэтому Windows воспроизводит звук, когда устройства находятся на достаточно близком расстоянии и обмениваются данными.</li> </ol>  <p>Все это осуществляется операционной системой Windows в автоматическом режиме и не требует выполнения каких-либо действий с вашей стороны. Дополнительную информацию об этих аспектах взаимодействия с пользователем можно найти в <a href="http://msdn.microsoft.com/ru-ru/library/windows/hardware/hh770524.aspx" target="_blank">Спецификации по реализации радиочастотной связи ближнего действия в Windows 8</a><u></u>. Учитывая все вышеизложенное, давайте рассмотрим несколько интересных сценариев использования NFC.</p>  <h2>Когда использовать NFC </h2>  <p>Используйте NFC, когда пользователю нужно выбрать что-то или кого-то в вашем приложении. NFC обеспечивает интуитивно понятный способ выбора, который часто оказывается быстрее (и удобнее), чем поиск вручную. Касание активирует процедуру, зависящую от используемого приложения. Это может быть что угодно, начиная от получения фотографии и заканчивая воспроизведением первого элемента списка воспроизведения. Конкретные действия, выполняемые после касания, определяются исключительно самим приложением. Поэтому для краткости мы назвали такое взаимодействие "Поднести и сделать".</p>  <p>Ниже приведено несколько примеров использования NFC для выбора объектов в приложении. Вы можете коснуться и…</p>  <ul>   <li><u>Получить информацию с афиши</u>: <a href="http://www.nfc-forum.org/news/pr/view?item_key=2c0cb92de7d47bbbe7c99f13912b3307fc03c1c6" target="_blank">метки NFC</a> — легкие и недорогие метки RFID, их стоимость составляет около 0,15–1,00 долл. США (цена зависит от затрат на печать). Они похожи на QR-коды, однако проще и быстрее в использовании. Касание метки удобнее фотографирования штрихкода (для которого требуется еще и правильный угол съемки). Производители все чаще помещают метки на афиши и плакаты в многолюдных местах, таких как аэропорты, станции метро и автобусные остановки. Такие метки могут содержать от 48 байт до 4 килобайт данных. Вы можете запрограммировать метку на открытие определенной страницы приложения. </li> </ul>  <ul>   <li><u>Обменяться контактными данными</u>: вместо того, чтобы по буквам диктовать свои контактные данные другу и надеяться на отсутствие ошибок, коснитесь устройствами для обмена соответствующей информацией. По аналогии с предыдущим сценарием вы можете занести свою информацию на визитку/метку с поддержкой технологии NFC либо обменяться этой информацией напрямую через приложение.</li>    <li><u>Воспроизвести любимую музыкальную радиостанцию</u>: собираетесь ли вы заняться спортом, садитесь в машину или просто отдыхаете дома, воспользуйтесь меткой NFC для прослушивания радиостанции. Вы даже можете запрограммировать разные радиостанции на разных метках, например использовать одну метку для спортзала, другую — для отдыха, третью — для сна.</li>    <li><u>Заказать ужин в популярном ресторане</u>: заказ блюд в таком ресторане в вечерние часы может занять достаточно много времени. Вместо этого коснитесь метки на столе для заказа блюд.</li>    <li><u>Сыграть в многопользовательскую игру с другом: </u>вы можете легко подключиться к многопользовательской игре, например "Морской бой", "Шахматы" или "Эрудит", вместе с другом, просто соприкоснувшись устройствами. После касания соединение поддерживается по внеполосному каналу с более широким диапазоном и более высокой пропускной способностью, например Bluetooth или Wi-Fi Direct. </li> </ul>  <p>Теперь мы имеем более-менее четкое представление о том, когда использовать NFC. Пришло время для по-настоящему интересной задачи — разработки приложения, использующего API-интерфейсы близкого взаимодействия (NFC) в Windows 8.</p>  <h2>Как реализовать NFC </h2>  <p>Как вы могли заметить, NFC упрощает выполнение множества повседневных задач для пользователей. Рассмотрим в качестве примера установку будильника. Я уверена, что практически каждый из нас несколько раз по ошибке устанавливал будильник на неправильное время. Когда за окнами уже ночь и вы хотите спать, не всегда удается сохранить концентрацию. NFC упрощает эту задачу, позволяя вам просто предварительно настроить метку, подтвердить операцию и спокойно лечь спать. Чтобы помочь пользователям с выполнением такой повседневной задачи, давайте представим, что вы разработали приложение будильника, позволяющее устанавливать сигнал с использованием метки NFC. Данную процедуру можно разделить на два сценария:</p>  <ol>   <li><u>Установка сигнала <b>на</b> метке</u>: метки NFC могут использоваться многократно, поэтому приложение должно предоставлять пользователю возможность программирования сигнала. Например, пользователь может запрограммировать разные сигналы — один для рабочих дней, а другой для выходных. Эта процедура называется публикацией данных в метке.</li>    <li><u>Установка сигнала <b>из</b> метки</u>: после касания метки пользователем приложение должно подтвердить установку сигнала. Это означает, что приложение может запускаться с контекстом (аргументами). </li> </ol>  <p>API NFC предоставляет несколько способов добиться желаемого, но для данного сценария я бы воспользовалась самым простым из них.</p>  <p>Давайте рассмотрим процедуру установки сигнала на метке NFC:</p>  <ol>   <li>Дмитрий запускает приложение будильника и задает время, например "7:00". Ничего необычного и требующего использования NFC здесь нет.</li>    <li>Дмитрий выбирает параметр "Установка сигнала на метке NFC". При этом приложение вызывает API-интерфейсы NFC для публикации информации, а именно строки идентификатора приложения и "07:00", на радиопередатчике NFC. Метки NFC используют стандартизированный формат сообщений под названием NDEF (NFC Defined Exchange Format). Вашему приложению <b>не </b>требуется самостоятельно преобразовывать данные в формат сообщения NDEF, поскольку за это отвечает операционная система Windows. Теперь пользователь может коснуться метки NFC.</li>    <li>Дмитрий соприкасается меткой с компьютером, и приложение подтверждает программирование метки. После касания метки важно дать пользователям понять, что приложение успешно запрограммировало метку. Как было указано ранее, большинство людей незнакомо с принципом касания компьютера, поэтому такое подтверждение придает пользователю уверенности в выполнении нужной операции. Приложение "узнает" об успешной передаче сообщения благодаря регистрации обработчика переданных сообщений.</li> </ol>  <p>API-интерфейсы NFC расположены в пространстве имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.proximity.aspx" target="_blank">Windows.Networking.Proximity</a>. Они вступают в игру на втором этапе, то есть после того, как пользователь выберет параметр "Установка сигнала на метке NFC". Сначала приложение инициализирует объект близкого взаимодействия. Он используется для определения появления метки (или устройства) в пределах радиуса действия или выхода за его пределы. Затем мы добавляем обработчик событий DeviceArrival. Этот обработчик распознает момент касания метки, после чего мы можем начинать запись информации в метку. Полезно сообщить пользователям о выполнении записи в метку, чтобы они не перемещали устройство из радиуса действия. Вы можете использовать это же событие для распознавания момента касания любого устройства с поддержкой близкого взаимодействия.</p>  <p>В следующем фрагменте кода показано, как инициализировать и добавить обработчик событий DeviceArrival.</p>  <p><strong>JavaScript</strong></p>  <blockquote>   <div>     <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> initializeProximityDevice() {<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.getDefault();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (proximityDevice) {<br />        proximityDevice.addEventListener(<span style="color: rgb(0, 96, 128);">&quot;devicearrived&quot;</span>, proximityDeviceArrived);<br />       <br />}<br />   <span style="color: rgb(0, 0, 255);">else</span> {<br />        <span style="color: rgb(0, 128, 0);">// No NFC radio on the PC, display an error message</span><br />    }<br /><br /><br /><span style="color: rgb(0, 0, 255);">function</span> proximityDeviceArrived(device) {<br />        <span style="color: rgb(0, 128, 0);">// Let the user know we’re ‘Writing to Tag’</span><br /><br />}<br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> InitializeProximityDevice()<br />{<br /><br />Windows.Networking.Proximity.ProximityDevice proximityDevice;<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br />    <span style="color: rgb(0, 0, 255);">if</span> (proximityDevice != <span style="color: rgb(0, 0, 255);">null</span>) {<br />        proximityDevice.DeviceArrived += ProximityDeviceArrived;<br />    <br />    }<br />    <span style="color: rgb(0, 0, 255);">else</span><br />    {<br />        <span style="color: rgb(0, 128, 0);">// No NFC radio on the PC, display an error message</span><br />    }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> ProximityDeviceArrived(Windows.Networking.Proximity.ProximityDevice device)<br />{<br />            <span style="color: rgb(0, 128, 0);">// Let the user know we’re ‘Writing to Tag’</span><br /><br />}<br /></pre>
  </div>
</blockquote>

<p>
  <br />Затем мы публикуем информацию в метке. Приложение публикует два элемента: строку идентификатора приложения, состоящую из идентификатора и платформы приложения, и аргументы запуска. Для Windows 8 идентификатор приложения — &lt;<a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.applicationmodel.packageid.familyname.aspx" target="_blank">имя семейства пакета</a>&gt;!&lt;<a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211415.aspx" target="_blank">идентификатор приложения</a>&gt;, а платформа приложения — "Windows". Вам следует скопировать значение идентификатора приложения из атрибута ID элемента Application в манифесте пакета приложения. Аргументом запуска является "07:00", то есть установленный пользователем сигнал. Давайте назовем все это <b>сообщением</b>.</p>

<p>Если приложение предназначено для работы на нескольких платформах, Windows позволяет опубликовать альтернативные значения идентификатора и платформы приложения. То есть вы можете касаться той же метки на другом устройстве, поддерживающем NFC, например на устройстве под управлением Windows Phone 8. Дополнительную информацию об <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.proximity.peerfinder.alternateidentities.aspx" target="_blank">альтернативных идентификаторах</a> можно найти на сайте MSDN.</p>

<p>Приложение публикует данные в метку с помощью метода <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh701134.aspx" target="_blank">publishBinaryMessage</a>. Этот метод принимает три параметра — messageType, message и функцию messageTransmittedHandler. Мы установим для messageType значение "LaunchApp:WriteTag", чтобы сообщить Windows о том, что приложению требуется записать информацию в метку NFC. Параметр message — это то сообщение, которое мы определили ранее (строка идентификатора приложения и аргументы запуска); нам потребуется хранить его в двоичном виде в буфере. Функция messageTransmittedHandler регистрируется для обратных вызовов. Это позволяет приложению узнать об успешной записи сообщения в метку. Мы будем это использовать, чтобы сообщить пользователю две вещи: мы успешно записали сообщение в метку, и метку можно больше не удерживать в пределах радиуса действия.</p>

<p>Сообщения публикуются до тех пор, пока мы не вызовем функцию StopPublishingMessage или не будет освобожден объект ProximityDevice. В данном примере мы будем использовать функцию останова. PublishBinaryMessage возвращает идентификатор публикации, этот же идентификатор публикации используется для остановки публикации сообщения на радиопередатчике NFC.</p>

<p>В следующем фрагменте кода показано, как записать данные в метку NFC:</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);"><span style="color: rgb(0, 0, 255);">var</span> proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">function</span> getAlarmTime(){<br /><br />    <span style="color: rgb(0, 128, 0);">// Grab time set by the user, call this variable ‘Alarm’</span><br />    <span style="color: rgb(0, 0, 255);">return</span> Alarm;<br /><br />}<br /><br /><span style="color: rgb(0, 0, 255);">function</span> publishLaunchApp() {<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br /><span style="color: rgb(0, 0, 255);">if</span> (proximityDevice) {<br />        <span style="color: rgb(0, 128, 0);">// The format of the app launch string is: &quot;&lt;args&gt;\tWindows\t&lt;AppName&gt;&quot;.</span><br />        <span style="color: rgb(0, 128, 0);">// The string is tab or null delimited.</span><br /><br />        <span style="color: rgb(0, 128, 0);">// The &lt;args&gt; string can be an empty string (&quot;&quot;).</span><br />        <span style="color: rgb(0, 0, 255);">var</span> launchArgs = getAlarmTime();<br /><br />        <span style="color: rgb(0, 128, 0);">// The format of the AppName is: PackageFamilyName!PRAID.</span><br />        <span style="color: rgb(0, 0, 255);">var</span> praid = <span style="color: rgb(0, 96, 128);">&quot;AlarmApp&quot;</span>; <span style="color: rgb(0, 128, 0);">// The Application Id value from your package.appxmanifest.</span><br /><br />        <span style="color: rgb(0, 0, 255);">var</span> appName = Windows.ApplicationModel.Package.current.id.familyName + <span style="color: rgb(0, 96, 128);">&quot;!&quot;</span> + praid;<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> launchAppMessage = launchArgs + <span style="color: rgb(0, 96, 128);">&quot;\tWindows\t&quot;</span> + appName;<br /><br />        <span style="color: rgb(0, 0, 255);">var</span> dataWriter = <span style="color: rgb(0, 0, 255);">new</span> Windows.Storage.Streams.DataWriter();<br />        dataWriter.unicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE;<br />        dataWriter.writeString(launchAppMessage);<br />        <span style="color: rgb(0, 0, 255);">var</span> launchAppPubId =<br />             proximityDevice.publishBinaryMessage(<br />                 <span style="color: rgb(0, 96, 128);">&quot;LaunchApp:WriteTag&quot;</span>, <br />                 dataWriter.detachBuffer(), <br />                 proximityWriteTagLaunchAppMessageTransmitCallback);<br />        <br />    <span style="color: rgb(0, 0, 255);">if</span> (launchAppPubId != -1) {<br />            <span style="color: rgb(0, 128, 0);">// Stop publishing the message on NFC radio</span><br />        proximityDevice.stopPublishingMessage(launchAppPubId);<br />    }<br /><br />     }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">function</span> proximityWriteTagLaunchAppMessageTransmitCallback() {<br />    <span style="color: rgb(0, 128, 0);">// Inform the user that: the message has been successfully written to a tag &amp; the tag no longer needs to be in range</span><br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">Windows.Networking.Proximity.ProximityDevice proximityDevice;<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">string</span> GetAlarmTime(){<br /><br />    <span style="color: rgb(0, 128, 0);">// Grab time set by the user, call this variable ‘Alarm’</span><br />    <span style="color: rgb(0, 0, 255);">return</span> Alarm;<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> PublishLaunchApp()<br />{<br />    proximityDevice = Windows.Networking.Proximity.ProximityDevice.GetDefault();<br /><br /><span style="color: rgb(0, 0, 255);">if</span> (proximityDevice != <span style="color: rgb(0, 0, 255);">null</span>)<br />    {<br />        <span style="color: rgb(0, 128, 0);">// The format of the app launch string is: &quot;&lt;args&gt;\tWindows\t&lt;AppName&gt;&quot;.</span><br />        <span style="color: rgb(0, 128, 0);">// The string is tab or null delimited.</span><br /><br />        <span style="color: rgb(0, 128, 0);">// The &lt;args&gt; string can be an empty string (&quot;&quot;).</span><br />        <span style="color: rgb(0, 0, 255);">string</span> launchArgs = getAlarmTime();<br /><br />        <span style="color: rgb(0, 128, 0);">// The format of the AppName is: PackageFamilyName!PRAID.</span><br />        <span style="color: rgb(0, 0, 255);">string</span> praid = <span style="color: rgb(0, 96, 128);">&quot;MyAppId&quot;</span>; <span style="color: rgb(0, 128, 0);">// The Application Id value from your package.appxmanifest.</span><br /><br />        <span style="color: rgb(0, 0, 255);">string</span> appName = Windows.ApplicationModel.Package.Current.Id.FamilyName + <span style="color: rgb(0, 96, 128);">&quot;!&quot;</span> + praid;<br /><br />        <span style="color: rgb(0, 0, 255);">string</span> launchAppMessage = launchArgs + <span style="color: rgb(0, 96, 128);">&quot;\tWindows\t&quot;</span> + appName;<br /><br />        var dataWriter = <span style="color: rgb(0, 0, 255);">new</span> Windows.Storage.Streams.DataWriter();<br />        dataWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;<br />        dataWriter.WriteString(launchAppMessage);<br />        var launchAppPubId =<br />        proximityDevice.PublishBinaryMessage(<br />            <span style="color: rgb(0, 96, 128);">&quot;LaunchApp:WriteTag&quot;</span>, dataWriter.DetachBuffer(), <br />            proximityWriteTagLaunchAppMessageTransmitCallback);<br />    <br />    <span style="color: rgb(0, 0, 255);">if</span> (launchAppPubId!= -1)<br />    {<br />        proximityDevice.StopPublishingMessage(launchAppPubId);<br />    <span style="color: rgb(0, 128, 0);">// Stop publishing the message on NFC radio</span><br />    }<br /><br />    }<br />}<br /><br /><span style="color: rgb(0, 0, 255);">private</span> <span style="color: rgb(0, 0, 255);">void</span> proximityWriteTagLaunchAppMessageTransmitCallback(<br />    Windows.Networking.Proximity.ProximityDevice sender,<br />    <span style="color: rgb(0, 0, 255);">long</span> messageId)<br />{<br />        <span style="color: rgb(0, 128, 0);">// Inform the user that: the message has been successfully written to a tag &amp; the tag no longer needs to be in range</span><br />}<br /></pre>
  </div>
</blockquote>

<br />Вот и все! Теперь вы знаете, как выполнить запись в метку NFC из приложения Магазина Windows. Здесь нет никаких сложностей, поэтому давайте перейдем к следующему сценарию — установке сигнала <b>из</b> метки. Рассмотрим процедуру считывания сигнала из метки NFC: 

<ol>
  <li>Дмитрий просматривает информацию на домашнем экране (составляет сообщение электронной почты, играет в игру или использует Windows) и понимает, что ему нужно установить сигнал будильника на утро понедельника. Он берет метку "Сигнал для рабочего дня" и касается ей своего компьютера. Отображается всплывающее уведомление, предлагающее запустить ваше приложение будильника. До этого момента всю работу выполняет Windows, ваше приложение бездействует.</li>

  <li>Дмитрий соглашается, и ваше приложение открывает экран "Подтвердить сигнал?" со временем "7:00". После принятия всплывающего уведомление Дмитрием Windows передает аргументы запуска (которые были описаны выше) в ваше приложение во время активации. Это называется контекстным запуском и соответствует запуску приложения, открытого на определенной странице.</li>

  <li>Дмитрий устанавливает сигнал. Ничего необычного и требующего использования NFC здесь нет.</li>
</ol>

<p>Получение аргументов запуска из метки NFC не вызывает никаких трудностей. Приложению требуется обработать контекстный запуск из метки NFC. Контекстный запуск аналогичен запуску приложения, открытого на определенной странице. Наши аргументы запуска задают сигнал "7:00" и используются приложением для отображения предлагаемого сигнала. Кроме того, если ваше приложение не установлено на компьютере, Windows предлагает Дмитрию установить его из Магазина Windows в автоматическом режиме.</p>

<p>В следующем фрагменте кода показано, как реализовать контекстный запуск.</p>

<p><strong>JavaScript</strong></p>

<blockquote>
  <div>
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">app.onactivated = <span style="color: rgb(0, 0, 255);">function</span> (args) {<br />    <span style="color: rgb(0, 0, 255);">if</span> (args.detail.kind === activation.ActivationKind.launch) {<br />        <span style="color: rgb(0, 0, 255);">if</span> (args.detail.arguments == <span style="color: rgb(0, 96, 128);">&quot;Windows.Networking.Proximity.PeerFinder:StreamSocket&quot;</span>) {<br />            <span style="color: rgb(0, 128, 0);">//do nothing here.</span><br />        }<br />        <span style="color: rgb(0, 0, 255);">else</span> {<br />    <span style="color: rgb(0, 128, 0);">// Use args.detail.arguments to parse out ’07.00’ string, and display to the user</span><br />        }<br /><br />        args.setPromise(WinJS.UI.processAll());<br />    }<br />}<br /></pre>
  </div>
</blockquote>

<div>
  <br /><strong>C#</strong></div>

<blockquote>
  <div id="codeSnippetWrapper">
    <pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: &quot;Courier New&quot;, courier, monospace; font-size: 8pt; direction: ltr; background-color: rgb(244, 244, 244);">async <span style="color: rgb(0, 0, 255);">protected</span> <span style="color: rgb(0, 0, 255);">override</span> <span style="color: rgb(0, 0, 255);">void</span> OnLaunched(LaunchActivatedEventArgs args)<br />        {<br />            <span style="color: rgb(0, 0, 255);">if</span> (args.Arguments == <span style="color: rgb(0, 96, 128);">&quot;Windows.Networking.Proximity.PeerFinder:StreamSocket&quot;</span>)<br />            {<br />                _isLaunchedByTap = <span style="color: rgb(0, 0, 255);">true</span>;<br />            }<br />            <span style="color: rgb(0, 0, 255);">else</span><br />            {<br /><span style="color: rgb(0, 128, 0);">// Use args.Arguments to parse out ’07.00’ string, and display to the user</span><br /><br />            }<br />            Window.Current.Activate();<br />        }<br /></pre>
  </div>
</blockquote>

<p>
  <br />Вот и все, что требуется от вашего приложения для поддержки чтения и записи метки NFC. Довольно просто для передовых технологий, не так ли? В завершение статьи рассмотрим еще один важный аспект — обработку ошибок.</p>

<h2>Обработка ошибок</h2>

<p>Существует несколько распространенных ошибок, с которыми может столкнуться ваше приложение.</p>

<ul>
  <li>Метка, к которой совершено касание, имеет формат, отличный от NDEF. Windows 8 не поддерживает автоматическое переформатирование метки в NDEF, поэтому вам требуется загрузить и установить модуль форматирования NDEF.</li>

  <li>Метка, к которой совершено касание, доступна только для чтения. Некоторые метки NFC могут быть заблокированы и доступны только для чтения (аналогично старым <a href="http://ru.wikipedia.org/wiki/VHS" target="_blank">видеокассетам VHS</a>).</li>

  <li>Метка, к которой совершено касание, слишком мала и не может вместить все данные.</li>

  <li>Компьютер пользователя не оснащен средствами NFC. Как я уже упоминала в начале, NFC — это развивающаяся технология, время повсеместного внедрения которой еще не настало. Чтобы проверить, поддерживает ли компьютер близкое взаимодействие, воспользуйтесь методом ProximityDevice.getDefault(), который возвращает значение NULL, когда установленные радиопередатчики NFC отсутствуют.</li>
</ul>

<h2>Это интересно и интуитивно понятно!</h2>

<p>Технология NFC прошла этап разработки и готова для массового потребителя, а Windows имеет экосистему и хорошо проработанный комплексный пользовательский интерфейс. Эта технология обладает огромным потенциалом по привнесению элемента интерактивности во взаимодействие устройств и приложений с пользователем. Все это очень интересно и интуитивно понятно. </p>

<p>NFC объединяет в себе множество различных аспектов, поэтому следите за новыми публикациями о других возможностях NFC в Windows 8 для разработчиков.</p>

<p>Дополнительную информацию по NFC и близкому взаимодействию можно найти в приведенных ниже ресурсах.</p>

<h2>Ресурсы</h2>

<div align="center">
  <table class="b8table" cellspacing="0" cellpadding="3" width="298" align="center" border="0"><tbody>
      <tr>
        <td valign="top" width="197">
          <p><strong>Ссылка</strong></p>
        </td>

        <td valign="top" width="99">
          <p><strong>Типы</strong></p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><u><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465215.aspx" target="_blank">Руководство по разработке с использованием возможностей близкого взаимодействия</a></u></p>
        </td>

        <td valign="top" width="99">
          <p>Документ</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br241250.aspx" target="_blank">API-интерфейсы близкого взаимодействия</a></p>
        </td>

        <td valign="top" width="99">
          <p>Документ</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh967765.aspx" target="_blank">Тестирование и диагностика приложений с поддержкой близкого взаимодействия</a></p>
        </td>

        <td valign="top" width="99">
          <p>Документ</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465223.aspx" target="_blank">Публикация и подписка (с дополнительными подробностями)</a></p>
        </td>

        <td valign="top" width="99">
          <p>Документ</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Proximity-Sample-88129731" target="_blank">Пример приложения с использованием близкого взаимодействия</a></p>
        </td>

        <td valign="top" width="99">
          <p>Пример</p>
        </td>
      </tr>

      <tr>
        <td valign="top" width="197">
          <p align="left"><a href="http://social.msdn.microsoft.com/Forums/ru-ru/category/windowsapps" target="_blank">Есть вопросы по близкому взаимодействию? Задайте их здесь</a></p>
        </td>

        <td valign="top" width="99">
          <p>Форум</p>
        </td>
      </tr>
    </tbody></table>
</div>

<p>Спасибо за внимание!</p>

<p>Прия Дандавейт (Priya Dandawate) 
  <br />Руководитель программы, устройства и сетевые возможности</p>

<p>Соавторы: Макс Моррис (Max Morris), Марзена Макута (Marzena Makuta), Майк Лохорт (Mike Loholt), Джейк Сабульски (Jake Sabulsky) и Вишал Матре (Vishal Mhatre)</p>

<!-- Title: “Разработка современного приложения с использованием NFC” Tags: “обмен информацией, NFC, радиочастотная связь ближнего действия, обмен файлами, связывание Bluetooth, обмен данными” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Создание подключенных приложений Магазина Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/103</link>
      <pubDate>Wed, 17 Apr 2013 13:58:00 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/04/17/103/</guid>
      <description><![CDATA[Нас повсюду окружают устройства, подключенные к сети. Даже новые модели холодильников и стиральных...]]></description>
      <content:encoded><![CDATA[<div class="postcontent">
<p>Нас повсюду окружают устройства, подключенные к сети. Даже новые модели холодильников и стиральных машин могут подключаться к Интернету и домашним сетям. Поэтому нет ничего удивительного в том, что пользователи ожидают от своих приложений аналогичного поведения. Такие "подключенные приложения" используют наиболее актуальный контент из Интернета &mdash; социальные сети, электронные СМИ, блоги и другие типы контента. Разработка подключенных приложений стала нормой, однако распространенные проблемы, такие как потеря подключения к сети, затраты в сети с лимитным тарифным планом или снижение производительности, все еще могут вызывать определенные трудности. Windows 8 существенно упрощает создание подключенных приложений.</p>
<p>В данной статье мы рассмотрим некоторые полезные советы по обеспечению быстрого, плавного и беспроблемного опыта работы, соответствующего концепции непрерывного подключения к сети, для пользователей приложений Магазина Windows:</p>
<ul>
<li>Выбирайте подходящий API для ваших сценариев.</li>
<li>Выбирайте правильные сетевые возможности.</li>
<li>Адаптируйте работу приложения для сетей с лимитным тарифным планом.</li>
<li>Реагируйте на изменения состояния сети.</li>
<li>Кэшируйте данные для обеспечения плавной работы.</li>
</ul>
<p>А теперь давайте подробно рассмотрим каждую из этих рекомендаций.</p>
<h2>Выбор подходящего API</h2>
<p>Если вы собираетесь строить дом, вам понадобятся подходящие инструменты. Нужен молоток для забивания гвоздей, пила для разрезания досок и отвертка для закручивания шурупов. Аналогичным образом при разработке подключенного приложения Магазина Windows вам нужны подходящие сетевые API. Windows 8 предлагает широкий спектр сетевых API, которые ваше приложение может использовать для взаимодействия с другими компьютерами и устройствами через Интернет или частные сети. Поэтому первым делом необходимо выяснить, какие сетевые компоненты требуются приложению.</p>
<p>Наиболее распространенный сценарий работы с сетью заключается в доступе к веб-сайту для получения или сохранения информации. В качестве простого примера можно привести игру, использующую веб-сайт для сохранения информации о пользователе и игрового счета. Более сложным примером является приложение, подключающееся к веб-службе на базе REST и использующее библиотеку, предоставляемую этой веб-службой, для считывания или сохранения информации. В Windows 8 есть несколько API, обеспечивающих подключение к веб-службам и веб-сайтам. С помощью этих API ваше приложение может осуществлять доступ к веб-службам, поддерживающим REST, или отправлять простые команды протокола HTTP (такие как GET и POST) на веб-сервер. API для обеспечения веб-доступа выбирается в зависимости от языка, используемого для разработки приложения:</p>
<ul>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh453379.aspx" target="_blank">XMLHTTPRequest</a> и <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229787.aspx" target="_blank">WinJS.xhr</a> &mdash; приложения, написанные на JavaScript и HTML.</li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/system.net.http.httpclient.aspx" target="_blank">HttpClient</a> &mdash; приложения, написанные на C# или Visual Basic .NET и XAML.</li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh831163.aspx" target="_blank">XML HTTP Request 2</a> (IXHR2) &mdash; приложения, написанные на C++ и XAML.</li>
</ul>
<p>В следующем фрагменте кода показано, как выполнить базовый запрос и ответ с использованием веб-службы на базе REST. В данном случае веб-служба может выполнить сценарий ASP.NET на веб-сервере.</p>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">function</span> makeXHRCall() {<br />    WinJS.xhr({ uri: <span style="color: #006080;">"http://www.microsoft.com/en-us/default.aspx&rdquo; }).done(<br /> function onComplete(result) {<br /> print(result.responseText);<br /> },<br /> function onError(err) {<br /> print("</span>Error: " + err.responseText);<br />        });<br />}</pre>
</div>
</blockquote>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">private</span> async <span style="color: #0000ff;">void</span> MakeHttpCall()<br />{<br />    HttpClient httpClient = <span style="color: #0000ff;">new</span> HttpClient();<br />    <span style="color: #0000ff;">try</span> {<br />        <span style="color: #0000ff;">string</span> response = await httpClient.GetStringAsync(<span style="color: #006080;">"http://www.microsoft.com/en-us/default.aspx"</span>);<br />    }<br />    <span style="color: #0000ff;">catch</span> (Exception) {<br />        <span style="color: #008000;">// Handle exception.</span><br />    }<br />}</pre>
</div>
</blockquote>
<p>Подробнее о <strong>WinJS.xhr</strong> можно прочитать в статье<a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh761502.aspx" target="_blank">Подключение к веб-службам (приложения Магазина Windows с использованием JavaScript и HTML)</a>. Дополнительную информацию об <strong>HttpClient</strong> можно найти в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/hh781239.aspx" target="_blank">Краткое руководство: подключение с использованием HttpClient (приложения Магазина Windows на C#, VB, C++ и XAML)</a> и в <a href="http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664" target="_blank">примере HttpClient</a>.</p>
<p>Еще одним распространенным сценарием работы в сети является такая загрузка или отправка файлов, когда передача может занимать некоторое время. В качестве примера можно привести приложение фотоальбома или галереи камеры, которому требуется отправлять фотографии или фотоальбомы в веб-службу или загружать их оттуда. Такая передача файлов может занимать много времени, поэтому совершенно незачем заставлять пользователя дожидаться ее окончания. API <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.backgroundtransfer.aspx" target="_blank">Windows.Networking.BackgroundTransfer</a> позволяет загружать или отправлять файлы даже в том случае, когда само приложение уже не работает. Приложение запускает передачу файлов, когда оно выполняется на переднем плане и находится в фокусе внимания, после чего Windows 8 продолжает передачу файлов в фоновом режиме, даже если само приложение уже не работает.</p>
<p>Более узкоспециализированным сценарием является доступ к сводному контенту. API <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.web.syndication.aspx" target="_blank">Windows.Web.Syndication</a> может получать веб-каналы в форматах RSS или Atom. Кроме того, API <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.web.atompub.aspx" target="_blank">Windows.Web.AtomPub</a> позволяет приложению публиковать данные в различных форматах AtomPub.</p>
<p>Для сценариев, для которых особый сетевой протокол более высокого уровня недоступен через API, среда выполнения Windows также поддерживает сокеты TCP и UDP (наряду с многоадресной рассылкой). API <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.sockets.aspx" target="_blank">Windows.Networking.Sockets</a> предоставляет <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.sockets.streamsocket.aspx" target="_blank">StreamSocket</a> (TCP) и <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.sockets.datagramsocket.aspx" target="_blank">DatagramSocket</a> (UDP) для реализации других протоколов более высокого уровня.</p>
<p><strong>Примечание. </strong>В Windows 8 представлен новый тип сокетов &mdash; <em>WebSocket</em>. Дополнительную информацию о сокетах WebSocket и их использовании можно найти в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh761442.aspx" target="_blank">Подключение с использованием WebSocket</a>.</p>
<p>В следующей таблице приведен более полный список поддерживаемых сетевых компонентов со ссылками на дополнительную информацию.</p>
<div align="center">&nbsp;
<table class="b8table" border="0" cellspacing="0" cellpadding="3" align="center">
<tbody>
<tr>
<td valign="top" width="217">
<p align="center"><strong>API</strong><strong></strong></p>
</td>
<td valign="top" width="221">
<p align="center"><strong>Функциональные возможности</strong><strong></strong></p>
</td>
<td valign="top" width="145">
<p align="center"><strong>Примеры</strong><strong></strong></p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.web.syndication.aspx" target="_blank">Windows.Web.Syndication</a></strong><strong></strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.web.atompub.aspx" target="_blank">Windows.Web.AtomPub</a></strong><strong></strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Получение веб-каналов в форматах RSS или Atom из нескольких разных версий. Эти API упрощают реализацию поддержки более новых форматов, таких как OData. Среда выполнения Windows также поддерживает протокол публикации Atom, что позволяет публиковать коллекции Atom. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh452973.aspx/" target="_blank">Доступ к сводному содержимому и управление им</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Syndication-sample-07ef6b0d" target="_blank">Пример использования Syndication</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/AtomPub-sample-c1fcdc8e" target="_blank">Пример использования AtomPub</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Средства чтения RSS</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.backgroundtransfer.aspx" target="_blank">Windows.Networking.BackgroundTransfer</a></strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Непрерывная и возобновляемая загрузка и отправка контента с минимальным объемом передаваемых данных, осуществляемая даже при отсутствии вызывающего приложения на переднем плане. Этот API поддерживает передачу контента с использованием протоколов HTTP, HTTPS и FTP. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh452979.aspx" target="_blank">Передача данных в фоновом режиме</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Background-Transfer-Sample-d7833f61" target="_blank">Пример передачи данных в фоновом режиме</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">SkyDrive</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Видео Xbox</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh453379.aspx" target="_blank">XMLHTTPRequest</a></strong><strong> (JavaScript</strong><strong>) </strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br229787.aspx" target="_blank">WinJS.xhr</a></strong><strong> </strong><strong>(JavaScript)</strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/system.net.http.httpclient.aspx" target="_blank">HttpClient</a></strong><strong> </strong><strong>(C#)</strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh831163.aspx">XML HTTP Request 2</a></strong><strong> (IXHR2)</strong><strong> </strong><strong>(C++)</strong><strong></strong></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Взаимодействие с веб-службами на базе REST и другими протоколами на основе HTTP. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh761502.aspx" target="_blank">Подключение к веб-службам</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/XHR-handling-navigation-50d03a7a" target="_blank">Пример XHR, обработки ошибок навигации и схем URL-адресов</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664" target="_blank">Пример использования HttpClient</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Карты Bing</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.proximity.aspx" target="_blank">Windows.Networking.Proximity</a></strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Обнаружение близкого взаимодействия двух устройств, после чего приложение может активировать их сетевое взаимодействие с использованием API-интерфейсов сокетов. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465229.aspx" target="_blank">Поддержка близкого взаимодействия и касания</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Proximity-Sample-88129731" target="_blank">Пример близкого взаимодействия</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Игры</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложения для совместной работы</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left"><strong><a href="http://msdn.microsoft.com/library/windows/apps/BR207928" target="_blank">Windows.Storage.Pickers</a></strong><strong></strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Взаимодействие с удаленными общими файловыми ресурсами. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh464959.aspx" target="_blank">Доступ к данным и файлам</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/File-picker-sample-9f294cba" target="_blank">Пример средства выбора файлов</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Xbox Music</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Фотографии</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left"><strong><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.sockets.aspx" target="_blank">Windows.Networking.Sockets</a></strong><strong></strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Подключение к службе, использующей протокол, не поддерживаемый уже упомянутыми API, например SMTP, MAPI или telnet, либо подключение к другому устройству в той же локальной сети. Используется также для приложений, которым для подключения к новой веб-службе через Интернет (включая прокси-серверы HTTP) требуется семантика, аналогичная семантике сокетов (асинхронная и двунаправленная). <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh452977.aspx" target="_blank">Подключение с помощью сокетов</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931" target="_blank">Пример StreamSocket</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/DatagramSocket-sample-76a7d82b" target="_blank">Пример DatagramSocket</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/Connecting-with-WebSockets-643b10ab" target="_blank">Пример подключения с использованием WebSocket</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left"><a href="http://code.msdn.microsoft.com/windowsapps/site/search?query=controlchanneltrigger&amp;f%5B0%5D.Value=controlchanneltrigger&amp;f%5B0%5D.Type=SearchText&amp;ac=3" target="_blank">Примеры ControlChannelTrigger</a></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Lync, доска для совместной работы или финансовая аналитика</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="217">
<p align="left">&nbsp;</p>
<p align="left"><strong><a href="http://msdn.microsoft.com/library/windows/apps/BR241587" target="_blank">Windows.Storage.ApplicationData</a></strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="221">
<p align="left">&nbsp;</p>
<p align="left">Windows 8 автоматически передает определенные данные приложения между устройствами пользователя. Такие перемещаемые данные упрощают работу с приложением на нескольких устройствах, например на компьютере в офисе и на планшете дома, и установку этого приложения на несколько устройств. <br />Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh465094.aspx" target="_blank">Руководство по перемещению данных приложения</a>.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="145">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<li>
<div align="left"><a href="http://go.microsoft.com/fwlink/p/?linkid=231478" target="_blank">Пример данных приложения</a></div>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<h2>Выбор правильных сетевых возможностей</h2>
<p>В состав модели безопасности приложений, используемой в Windows 8, входит сетевая изоляция. Windows активно отслеживает границы сети и применяет ограничения сетевого доступа для обеспечения сетевой изоляции. При правильном развертывании эти возможности помогают защитить пользователей и приложения от вредоносных атак.</p>
<p>Приложения должны объявлять возможности сетевой изоляции, чтобы определить область сетевого доступа. Без объявления этих возможностей приложение не получит доступ к сетевым ресурсам. Дополнительную информацию о том, как Windows обеспечивает сетевую изоляцию приложений, можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/Hh770532.aspx" target="_blank">Настройка сетевых возможностей</a>.</p>
<p>Обратите внимание на то, что вы не можете использовать сеть в качестве механизма межпроцессного взаимодействия между приложениями Магазина Windows и классическими приложениями, находящимися на одном устройстве. Таким образом, вы не можете использовать петлевые IP-адреса в приложении Магазина Windows. В процессе разработки можно воспользоваться ограниченным числом исключений, позволяющих использовать петлевые IP-адреса при работе в отладчике Visual Studio. Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/Hh780593.aspx" target="_blank">Включение замыкания на себя и устранение неполадок сетевой изоляции</a>.</p>
<p>Запросы на доступ к сети делятся на две категории:</p>
<ol>
<li><strong>Исходящие запросы, инициированные клиентом</strong>. Ваше приложение выступает в роли клиента и инициирует доступ к сети, отправляя начальный сетевой запрос на удаленный компьютер, обычно сервер. Приложение отправляет один или несколько запросов на сервер, а сервер отправляет обратно один или несколько ответов. Например, к этой категории относится весь трафик, передаваемый из приложения веб-клиента на веб-сервер.</li>
<li><strong>Незапрошенные входящие запросы</strong>. Ваше приложение выступает в роли сетевого сервера и выполняет прослушивание на предмет входящих сетевых запросов с удаленного компьютера. Удаленный компьютер инициирует сетевой доступ, отправляя начальный запрос вашему приложению, выступающему в роли сервера. Удаленный компьютер отправляет один или несколько запросов вашему приложению, которое отправляет обратно на удаленный компьютер один или несколько ответов. Например, к этой категории относится приложение, играющее роль сервера мультимедиа.</li>
</ol>
<p>Следуйте принципу предоставления минимальных прав и добавляйте только те возможности, которые необходимы приложению. Вашему приложению могут требоваться только исходящие запросы, инициированные клиентом, а может также требоваться и возможность получения незапрошенных входящих запросов. Некоторые приложения также могут нуждаться в доступе к учетным данным пользователей и сертификатам для проверки подлинности по сети.</p>
<p>В следующей таблице приведены сведения о возможностях сетевой изоляции и других связанных с ними возможностях, которые часто требуются подключенным приложениям. Первые три из перечисленных возможностей сетевой изоляции &mdash; это основные возможности, используемые подключенными приложениями. На практике подключенное приложение должно реализовывать хотя бы одну из этих трех возможностей. Остальные элементы таблицы отражают дополнительные возможности, которые часто требуются некоторым подключенным приложениям.</p>
<p>&nbsp;</p>
<div align="center">
<table class="b8table" style="width: 612px;" border="0" cellspacing="0" cellpadding="3" align="center">
<tbody>
<tr>
<td valign="top" width="146">
<p><strong>Сетевая возможность</strong></p>
</td>
<td valign="top" width="273">
<p><strong>Описание</strong></p>
</td>
<td valign="top" width="191">
<p><strong>Примеры приложений</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">Интернет (клиент)</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Предоставляет исходящий доступ к Интернету и сетям в общественных местах, таких как аэропорты или кафе. Данная возможность должна объявляться большинством приложений, которым требуется доступ в Интернет.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Средства чтения RSS</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Социальные сети</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Игры</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">&nbsp;</p>
<p align="left">Интернет (клиент и сервер)</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Предоставляет входящий и исходящий доступ к Интернету и сетям в общественных местах, таких как аэропорты или кафе. Входящий доступ к критически важным портам всегда блокируется. Данная возможность представляет собой расширение возможности "Интернет (клиент)", поэтому объявлять обе эти возможности не требуется.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложения P2P</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Многопользовательские игры, в которых обнаружение игроков осуществляется посредством многоадресной рассылки</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">&nbsp;</p>
<p align="left">Частные сети (клиент и сервер)</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Предоставляет входящий и исходящий доступ к сети в частных расположениях, которым пользователь доверяет. Обычно это домашние или рабочие сети. Входящий доступ к критически важным портам всегда блокируется.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложения, осуществляющие доступ к данным на запоминающих устройствах, подключаемых к сети (NAS)</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Бизнес-приложения</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Многопользовательские игры, в которых обнаружение игроков осуществляется посредством многоадресной рассылки в частной (домашней или рабочей) сети</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">&nbsp;</p>
<p align="left">Близкое взаимодействие</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Требуется для близкого NFC-взаимодействия с устройствами. Позволяет приложениям получить доступ к сети для подключения к находящемуся поблизости устройству, при этом пользователь может отправить или принять приглашение.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Многопользовательские игры, в которых игроки находятся поблизости друг от друга<em></em></div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">&nbsp;</p>
<p align="left">Корпоративная проверка подлинности</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Предоставляет возможность подключения к ресурсам корпоративной интрасети, для доступа к которым необходимы учетные данные домена.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Бизнес-приложения</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="146">
<p align="left">&nbsp;</p>
<p align="left">Общие сертификаты пользователей</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="273">
<p align="left">&nbsp;</p>
<p align="left">Предоставляет возможность доступа к сертификатам программного и аппаратного обеспечения, таким как сертификаты смарт-карт, для проверки личности пользователя. При вызове соответствующих API во время выполнения пользователь должен совершить действие (например, вставить карту или выбрать сертификат).</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="191">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложения виртуальной частной сети</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<li>
<div align="left">Бизнес-приложения</div>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<p>Используйте следующий контрольный список, чтобы убедиться, что для вашего приложения настроена сетевая изоляция:</p>
<ul>
<li>Определите направление доступа к сети, необходимого вашему приложению. Приложению могут требоваться только исходящие запросы, инициированные клиентом, незапрошенные входящие запросы или запросы обоих типов.</li>
<li>Определите тип сетевых ресурсов, с которыми будет взаимодействовать ваше приложение: надежные ресурсы в домашней или рабочей сети, ресурсы в Интернете или ресурсы обоих этих типов.</li>
<li>Настройте минимально необходимые возможности сетевой изоляции в манифесте приложения. Для этого вы можете использовать <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br230259.aspx" target="_blank">конструктор манифеста приложения</a> в Microsoft Visual Studio 2012 либо <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br211477.aspx" target="_blank">добавить их вручную</a>.</li>
<li>Выполните развертывание приложения и запустите его, чтобы протестировать с применением доступных диагностических средств сетевой изоляции. Подробнее можно прочитать в статье <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/Hh780593.aspx" target="_blank">Включение замыкания на себя и устранение неполадок сетевой изоляции</a>.</li>
</ul>
<p>На следующих снимках экрана показано, как включить сетевые возможности с помощью <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/br230259.aspx" target="_blank">конструктора манифеста приложения</a> в Microsoft Visual Studio 2012.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7268.app-manifest-design_47107BBF.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7268.app_2D00_manifest_2D00_design_5F00_47107BBF.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="Выбор сетевых возможностей в package.appxmanifest вашего приложения в Visual Studio 2012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7752.app-manifest-design_thumb_5EC7B325.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7752.app_2D00_manifest_2D00_design_5F00_thumb_5F00_5EC7B325.png" alt="Выбор сетевых возможностей в package.appxmanifest вашего приложения в Visual Studio 2012" width="600" height="318" border="0" /></a></p>
<p align="center"><em>Выбор сетевых возможностей в package.appxmanifest вашего приложения в Visual Studio 2012</em></p>
<h2>Адаптация работы приложения для сетей с лимитным тарифным планом</h2>
<p>Вспомните прошлый раз, когда вы почти исчерпали месячную квоту на трафик или ездили за границу. В таких ситуациях мне приходилось пользоваться устройством и приложениями очень осторожно, чтобы избежать излишних затрат на передачу данных по сети.</p>
<p>Windows 8 помогает решить эту проблему, позволяя приложениям отслеживать доступные сетевые ресурсы и работать в соответствующем режиме при подключении к сетям с лимитным тарифным планом. Чтобы пользователь мог действовать более уверенно, ваше приложение может сообщать ему о ситуациях, в которых возможно взимание дополнительной платы, и адаптировать режим работы таким образом, чтобы избежать таких затрат или сократить их.</p>
<p>API-интерфейс <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.aspx" target="_blank">Windows.Networking.Connectivity</a> предоставляет сведения о типе и стоимости сетевого подключения. Это позволяет вашему приложению определить, имеет ли смысл использовать сетевые ресурсы в обычном режиме, умеренно или с запросом разрешения у пользователя.</p>
<p>API-интерфейс <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectionprofile.aspx" target="_blank">ConnectionProfile</a> представляет сетевое подключение. Потребность в адаптации режима работы ваше приложение может определять с помощью <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> из <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectionprofile.aspx" target="_blank">ConnectionProfile</a>. Свойство <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> указывает тип сетевого подключения. Возможны четыре значения:</p>
<ul>
<li><strong>Unrestricted</strong> &mdash; использование этого сетевого подключения не ограничивается. Оно не связано с затратами на использование или ограничениями объема передаваемых данных.</li>
<li><strong>Fixed</strong> &mdash; использование этого сетевого подключения не ограничивается до определенного предела.</li>
<li><strong>Variable</strong> &mdash; использование этого сетевого подключения оплачивается по количеству байт.</li>
<li><strong>Unknown</strong> &mdash; информация о стоимости использования этого сетевого подключения недоступна.</li>
</ul>
<p>Несколько логических свойств для <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> предоставляют дополнительную информацию.</p>
<ul>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.roaming.aspx" target="_blank">Roaming</a> &mdash; подключение к сети за пределами зоны охвата домашнего поставщика услуг Интернета.</li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.approachingdatalimit.aspx" target="_blank">ApproachingDataLimit</a> &mdash; для подключения почти исчерпан лимит использования, предусмотренный тарифным планом.</li>
<li><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.overdatalimit.aspx" target="_blank">OverDataLimit</a> &mdash; для подключения исчерпан лимит использования, предусмотренный тарифным планом.</li>
</ul>
<p>Предусмотрите в своем приложении реагирование на ситуации, обозначенные этими свойствами. Если подключение имеет свойство <strong>Roaming</strong>, затраты на передачу данных по сети могут быть очень высокими. Когда <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> имеет значение <strong>Variable</strong>, используется сеть с лимитным тарифным планом, где пользователь платит за объем данных, отправленных или принятых по этой сети. Если <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> имеет значение <strong>Fixed</strong>, следует уделить внимание ситуации, когда пользователь превысил либо почти превысил лимит трафика.</p>
<p>Используя эту информацию, ваше приложение может следовать приведенным рекомендациям, чтобы выбрать оптимальный способ использования сетевых ресурсов.</p>
<div align="center">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<table class="b8table" border="0" cellspacing="0" cellpadding="3" align="center">
<tbody>
<tr>
<td valign="top" width="97">
<p><strong>Поведение</strong></p>
</td>
<td valign="top" width="150">
<p><strong>Стоимость использования подключения</strong></p>
</td>
<td valign="top" width="168">
<p><strong>Рекомендации для приложений</strong></p>
</td>
<td valign="top" width="175">
<p><strong>Примеры</strong></p>
</td>
</tr>
<tr>
<td valign="top" width="97">
<p align="left">Обычное использование</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="150">
<p align="left">&nbsp;</p>
<p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> имеет значение <strong>Unrestricted</strong> или <strong>Unknown</strong>, а значение <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> отлично от <strong>Roaming</strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="168">
<p align="left">&nbsp;</p>
<p align="left">Приложение не применяет какие-либо ограничения. Приложение считает, что подключение работает <strong>без ограничений</strong> с точки зрения затрат или объема передаваемых данных.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="175">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложение проигрывателя мультимедиа может воспроизвести весь фильм с высоким разрешением.</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложение может загрузить большой файл без ограничений или запросов.</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="97">
<p align="left">&nbsp;</p>
<p align="left">Умеренное использование</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="150">
<p align="left">&nbsp;</p>
<p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> имеет значение <strong>Fixed</strong> или <strong>Variable</strong>, а значение <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> отлично от <strong>Roaming</strong> или <strong>OverDataLimit</strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="168">
<p align="left">&nbsp;</p>
<p align="left">Приложение применяет ограничения, направленные на оптимизацию использования сети, для обработки операций в сетях с лимитным тарифным планом.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="175">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложение проигрывателя мультимедиа может воспроизводить фильмы с более низким разрешением.</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложение может откладывать загрузку данных, не имеющих критически важного значения.</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
</td>
</tr>
<tr>
<td valign="top" width="97">
<p align="left">&nbsp;</p>
<p align="left">Явное согласие</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="150">
<p align="left">&nbsp;</p>
<p align="left"><a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.aspx" target="_blank">ConnectionCost</a> имеет значение <strong>Roaming</strong> или <strong>OverDataLimit</strong></p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="168">
<p align="left">&nbsp;</p>
<p align="left">Приложение обрабатывает исключительные случаи, когда стоимость доступа к сети значительно больше стоимости, предусмотренной тарифным планом.</p>
<p align="left">&nbsp;</p>
</td>
<td valign="top" width="175">
<p align="left">&nbsp;</p>
<p align="left">&nbsp;</p>
<ul>
<ul>
<li>
<div align="left">Приложение запрашивает разрешение пользователя на доступ к сети.</div>
</li>
</ul>
</ul>
<p align="left">&nbsp;</p>
<ul>
<li>
<div align="left">Приложение приостанавливает все фоновые операции по обмену данными с сетью.<em></em></div>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<p>Этот пример кода проверяет стоимость использования подключения и выводит предложения относительно подходящего режима работы приложения.</p>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">var</span> CostGuidance = { Normal: 0, Conservative: 1, OptIn: 2 };<br /><span style="color: #008000;">// GetCostGuidance returns an object with a Cost (with value of CostGuidance), </span><br /><span style="color: #008000;">// CostName (a string) and Reason, which says why the cost is what it is.</span><br /><span style="color: #0000ff;">function</span> GetCostGuidance() <br />{<br />    <span style="color: #0000ff;">var</span> connectionCost = Windows.Networking.Connectivity.NetworkInformation.getInternetConnectionProfile().getConnectionCost();<br />    <span style="color: #0000ff;">var</span> networkCostConstants = Windows.Networking.Connectivity.NetworkCostType;<br />    <span style="color: #0000ff;">var</span> Retval = <span style="color: #0000ff;">new</span> Object();<br />    <span style="color: #0000ff;">if</span> (connectionCost.roaming || connectionCost.overDataLimit)<br />    {<br />        Retval.Cost = CostGuidance.OptIn;<br />        Retval.CostName = <span style="color: #006080;">"OptIn"</span>;<br />        Retval.Reason = connectionCost.roaming<br />            ? <span style="color: #006080;">"Connection is roaming; using the connection may result in additional charge."</span><br />            : <span style="color: #006080;">"Connection has exceeded the usage cap limit."</span>;<br />    }<br />    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (connectionCost.networkCostType == networkCostConstants.<span style="color: #0000ff;">fixed</span><br />        || connectionCost.networkCostType == networkCostConstants.variable)<br />    {<br />        Retval.Cost = CostGuidance.conservative;<br />        Retval.CostName = <span style="color: #006080;">"Conservative"</span>;<br />        Retval.Reason = connectionCost.networkCostType == NetworkCostType.<span style="color: #0000ff;">fixed</span><br />            ? <span style="color: #006080;">"Connection has limited allowed usage."</span><br />            : <span style="color: #006080;">"Connection is charged based on usage. "</span>;<br />    }<br />    <span style="color: #0000ff;">else</span><br />    {<br />        Retval.Cost = CostGuidance.Normal;<br />        Retval.CostName = <span style="color: #006080;">"Normal"</span>;<br />        Retval.Reason = connectionCost.networkCostType == networkCostConstants.unknown<br />            ? <span style="color: #006080;">"Connection is unknown."</span><br />            : <span style="color: #006080;">"Connection cost is unrestricted."</span>;<br />    }<br /><br />    <span style="color: #0000ff;">return</span> Retval;<br />}</pre>
</div>
</blockquote>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> NetworkCost { Normal, Conservative, OptIn };<br /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> CostGuidance<br />{<br />    <span style="color: #0000ff;">public</span> CostGuidance()<br />    {<br />        var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();<br />        Init(connectionCost);<br />    }<br />    <span style="color: #0000ff;">public</span> NetworkCost Cost { get; <span style="color: #0000ff;">private</span> set; }<br />    <span style="color: #0000ff;">public</span> String Reason { get; <span style="color: #0000ff;">private</span> set; }<br /><br /><br />    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Init(ConnectionCost connectionCost)<br />    {<br />        <span style="color: #0000ff;">if</span> (connectionCost == <span style="color: #0000ff;">null</span>) <span style="color: #0000ff;">return</span>;<br />        <span style="color: #0000ff;">if</span> (connectionCost.Roaming || connectionCost.OverDataLimit)<br />        {<br />            Cost = NetworkCost.OptIn;<br />            Reason = connectionCost.Roaming<br />                ? <span style="color: #006080;">"Connection is roaming; using the connection may result in additional charge."</span><br />                : <span style="color: #006080;">"Connection has exceeded the usage cap limit."</span>;<br />        }<br />        <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (connectionCost.NetworkCostType == NetworkCostType.Fixed<br />            || connectionCost.NetworkCostType == NetworkCostType.Variable)<br />        {<br />            Cost = NetworkCost.Conservative;<br />            Reason = connectionCost.NetworkCostType == NetworkCostType.Fixed<br />                ? <span style="color: #006080;">"Connection has limited allowed usage."</span><br />                : <span style="color: #006080;">"Connection is charged based on usage. "</span>;<br />        }<br />        <span style="color: #0000ff;">else</span><br />        {<br />            Cost = NetworkCost.Normal;<br />            Reason = connectionCost.NetworkCostType == NetworkCostType.Unknown<br />                ? <span style="color: #006080;">"Connection is unknown."</span><br />                : <span style="color: #006080;">"Connection cost is unrestricted."</span>;<br />        }<br />    }<br />}</pre>
</div>
</blockquote>
<p>Используйте <a href="http://code.msdn.microsoft.com/windowsapps/Network-Information-Sample-63aaa201" target="_blank">пример сетевой информации</a>, чтобы больше узнать об адаптации поведения приложения к работе в сетях с лимитным тарифным планом.</p>
<p>Пользователи также могут запустить диспетчер задач для просмотра объема сетевых данных, используемых каждым из приложений. На этом снимке экрана приведен соответствующий пример.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/5618.task-manager_6C99F920.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/5618.task_2D00_manager_5F00_6C99F920.png"><img style="border: 0px currentcolor; margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="На вкладке &quot;Журнал приложений&quot; в диспетчере задач пользователи могут просмотреть данные об использовании ресурсов центрального процессора и сети различными приложениями" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/3554.task-manager_thumb_4C7EEC63.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/3554.task_2D00_manager_5F00_thumb_5F00_4C7EEC63.png" alt="На вкладке &quot;Журнал приложений&quot; в диспетчере задач пользователи могут просмотреть данные об использовании ресурсов центрального процессора и сети различными приложениями" width="600" height="545" border="0" /></a></p>
<p align="center"><em>На вкладке "Журнал приложений" в диспетчере задач пользователи могут просмотреть данные об использовании ресурсов центрального процессора и сети различными приложениями</em></p>
<h2>Реагирование на изменения состояния сети</h2>
<p>В любом сценарии работы мобильного устройства сети могут как появляться, так и пропадать. В гараже или доме пользователя мобильная широкополосная сеть 3G или 4G, в отличие от сети Wi-Fi, может становиться недоступной. Аналогичным образом подключение к сети Wi-Fi может прерываться, когда пользователь выходит из дома. Иногда доступные сети могут вообще отсутствовать. Учитывая распространение Wi-Fi и мобильных широкополосных сетей, такие изменения в состоянии сетевого подключения будут возникать достаточно часто.</p>
<p>Событие <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a> указывает на возможное изменение <em>стоимости</em> или <em>вариантов подключения</em>. Чтобы реагировать на возникающие изменения состояния сети и обеспечить комфортную работу пользователя, реализуйте в своих подключенных приложениях следующие рекомендации.</p>
<h3>Потеря подключения из-за ошибки</h3>
<p>В большинстве случаев подключение можно восстановить, просто попытавшись повторить сетевую операцию. В случае неудачи дождитесь события <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>. Мы рекомендуем использовать в приложениях возрастающий интервал между повторными попытками, начинающийся с 50 миллисекунд и экспоненциально возрастающий в случае дальнейших сбоев подключения.</p>
<h3>Потеря подключения к сети</h3>
<p>Уведомите пользователя о потере подключения к сети, затем зарегистрируйтесь и дождитесь события <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>.</p>
<h3>Доступность новой сети</h3>
<p>В некоторых случаях устройство подключается к нескольким сетям. Например, пользователь может подключиться к мобильной широкополосной сети и общаться с друзьями в приложении для обмена сообщениями Windows 8 до прибытия домой, после чего он может подключиться к сети, работающей без ограничений трафика. По умолчанию Windows 8 отдает предпочтение бесплатной сети перед сетью с лимитным тарифным планом и более быстрой сети перед медленной. Однако автоматическое переключение имеющихся подключений, установленных приложением, на новую сеть не выполняется. Об этом должно заботиться приложение, поскольку только оно может принять оптимальное решение о переключении на новую сеть.</p>
<p>Например, если видеопоток близок к завершению, переключаться на новую сеть не имеет смысла. Однако если текущая сеть теряет пакеты, работает слишком медленно или для завершения потока требуется дополнительное время, переключение на новую сеть может оказаться оптимальным решением.</p>
<p>Если вы считаете, что ваше приложение будет часто сталкиваться с необходимостью смены сетей, при обнаружении новой сети следуйте приведенным ниже рекомендациям:</p>
<ol>
<li>Проверьте стоимость использования текущей и новой сетей. Если переключение на новую сеть имеет смысл, попробуйте установить новое сетевое подключение и повторить сетевую операцию в соответствии с приведенными выше указаниями. Windows 8 автоматически выбирает сеть без ограничений трафика вместо сети с лимитным тарифным планом и более быструю сеть вместо медленной.</li>
<li>Если подключение к новой сети выполнено успешно, используйте его в приложении и отмените исходную сетевую операцию, использующую предыдущую сеть, если такое соединение уже установлено.</li>
</ol>
<h3>Изменение стоимости сетевого подключения</h3>
<p>Изменение стоимости сетевого подключения может произойти, когда <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> имеет значение <strong>Fixed</strong> и пользователь превысил либо почти превысил лимит трафика. Кроме того, изменение стоимости сетевого подключения может произойти, когда для <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.networkcosttype.aspx" target="_blank">NetworkCostType</a> устанавливается значение <strong>Variable</strong> или для <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.connectioncost.roaming.aspx" target="_blank">Roaming</a> устанавливается значение true. В этих случаях адаптируйте поведение приложения, следуя рекомендациям из предыдущего пункта.</p>
<p>В следующих примерах кода используется событие <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a> для обеспечения удобного опыта работы с приложением при различных изменениях состояния сети. В обоих примерах используется глобальная логическая переменная <em>registeredNetworkStatusNotification,</em> для которой изначально задано значение <strong>false</strong>.</p>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #008000;">// Register for NetworkStatusChanged notifications, and display new </span><br /><span style="color: #008000;">// Internet ConnectionProfile info upon network status change.</span><br /><span style="color: #0000ff;">function</span> registerForNetworkStatusChange() {<br />    <span style="color: #0000ff;">try</span> {<br /><br />        <span style="color: #008000;">// Register for network status change notifications.</span><br />        <span style="color: #0000ff;">if</span> (!registeredNetworkStatusNotification) {<br />            <span style="color: #0000ff;">var</span> networkInfo.addEventListener(<span style="color: #006080;">"networkstatuschanged"</span>, onNetworkStatusChange);<br />            registeredNetworkStatusNotification = <span style="color: #0000ff;">true</span>;<br />        }<br />    }<br />    <span style="color: #0000ff;">catch</span> (e) {<br />        print(<span style="color: #006080;">"An unexpected exception occurred: "</span> + e.name + <span style="color: #006080;">": "</span> + e.message);<br />    }<br />}<br /><br /><span style="color: #008000;">// Event handler for NetworkStatusChanged event</span><br /><span style="color: #0000ff;">function</span> onNetworkStatusChange(sender) {<br />    <span style="color: #0000ff;">try</span> {<br />        <span style="color: #008000;">// Get the ConnectionProfile that is currently used to connect </span><br />        <span style="color: #008000;">// to the Internet.</span><br />        <span style="color: #0000ff;">var</span> internetProfile = networkInfo.getInternetConnectionProfile();<br />        <span style="color: #0000ff;">if</span> (internetProfile === <span style="color: #0000ff;">null</span>) {<br />            print(<span style="color: #006080;">"Not connected to Internet\n\r"</span>);<br />        }<br />        <span style="color: #0000ff;">else</span> {<br />            internetProfileInfo += getConnectionProfileInfo(internetProfile) + <span style="color: #006080;">"\n\r"</span>;<br />            print(internetProfileInfo);<br />        }<br />        internetProfileInfo = <span style="color: #006080;">""</span>;<br />    }<br />    <span style="color: #0000ff;">catch</span> (e) {<br />        print(<span style="color: #006080;">"An unexpected exception occurred: "</span> + e.name + <span style="color: #006080;">": "</span> + e.message);<br />    }<br />}</pre>
</div>
</blockquote>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #008000;">// Register for NetworkStatusChanged notifications, and display new </span><br /><span style="color: #008000;">// Internet ConnectionProfile info upon network status change.</span><br /><span style="color: #0000ff;">void</span> NetworkStatusChange()<br />{<br />    <span style="color: #008000;">// Register for network status change notifications.</span><br />    <span style="color: #0000ff;">try</span><br />    {<br />        var networkStatusCallback = <span style="color: #0000ff;">new</span> NetworkStatusChangedEventHandler(OnNetworkStatusChange);<br />        <span style="color: #0000ff;">if</span> (!registeredNetworkStatusNotification)<br />        {<br />            NetworkInformation.NetworkStatusChanged += networkStatusCallback;<br />            registeredNetworkStatusNotification = <span style="color: #0000ff;">true</span>;<br />        }<br />    }<br />    <span style="color: #0000ff;">catch</span> (Exception ex)<br />    {<br />        rootPage.NotifyUser(<span style="color: #006080;">"Unexpected exception occurred: "</span> + ex.ToString(), NotifyType.ErrorMessage);<br />    }<br />}<br /><br /><span style="color: #008000;">// Event handler for NetworkStatusChanged event</span><br />async <span style="color: #0000ff;">void</span> OnNetworkStatusChange(<span style="color: #0000ff;">object</span> sender)<br />{<br />    <span style="color: #0000ff;">try</span><br />    {<br />        <span style="color: #008000;">// Get the ConnectionProfile that is currently used to connect </span><br />        <span style="color: #008000;">// to the Internet </span><br />        ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();<br /><br />        <span style="color: #0000ff;">if</span> (InternetConnectionProfile == <span style="color: #0000ff;">null</span>)<br />        {<br />            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =&gt;<br />            {<br />                rootPage.NotifyUser(<span style="color: #006080;">"Not connected to Internet\n"</span>, NotifyType.StatusMessage);<br />            });<br />        }<br />        <span style="color: #0000ff;">else</span><br />        {<br />            connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);<br />            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =&gt;<br />            {<br />                rootPage.NotifyUser(connectionProfileInfo, NotifyType.StatusMessage);<br />            });<br />        }<br />        internetProfileInfo = <span style="color: #006080;">""</span>;<br />    }<br />    <span style="color: #0000ff;">catch</span> (Exception ex)<br />    {<br />        rootPage.NotifyUser(<span style="color: #006080;">"Unexpected exception occurred: "</span> + ex.ToString(), NotifyType.ErrorMessage);<br />    }<br />}</pre>
</div>
</blockquote>
<p>Чтобы больше узнать о событии <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.networking.connectivity.networkinformation.networkstatuschanged" target="_blank">NetworkStatusChanged</a>, ознакомьтесь со статьей <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/hh700376.aspx" target="_blank">Краткое руководство: управление событиями подключения и изменениями доступности</a> и <a href="http://code.msdn.microsoft.com/windowsapps/Network-Information-Sample-63aaa201" target="_blank">примером сетевой информации</a>.</p>
<h2>Кэширование данных для обеспечения плавной работы</h2>
<p>Кэширование контента на диск обеспечивает быструю и плавную работу приложения. Например, приложение для чтения RSS-каналов может мгновенно отображать веб-каналы, кэшированные на диск во время предыдущего сеанса. По мере получения новых веб-каналов приложение обновляет этот контент. Кэширование позволяет сразу после запуска приложения отобразить некоторый контент, который пользователь может изучать, пока загружается новый контент.</p>
<p>Windows 8 предоставляет класс <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.storage.applicationdata.aspx" target="_blank">ApplicationData</a><strong></strong> в пространстве имен <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.storage.aspx" target="_blank">Windows.Storage</a><strong></strong>. Этот класс предоставляет доступ к хранилищу данных приложения. Это хранилище состоит из файлов и параметров, являющихся локальными по отношению к устройству, перемещаемых между несколькими устройствами или являющихся временными.</p>
<p>Файлы оптимально подходят для хранения больших наборов данных, баз данных или данных в распространенном формате. Файлы могут находиться в перемещаемых, локальных или временных папках. Вот что это значит:</p>
<ul>
<li>Перемещаемые файлы синхронизируются на нескольких компьютерах и устройствах, где пользователи выполнили вход с использованием подключенных учетных записей. Перемещение файлов осуществляется не мгновенно. Система анализирует несколько факторов, определяя подходящий момент для отправки данных. Старайтесь не допускать превышения квоты (доступной через свойство <a href="http://msdn.microsoft.com/ru-ru/library/windows/apps/windows.storage.applicationdata.roamingstoragequota.aspx" target="_blank">RoamingStorageQuota</a><strong></strong>) на объем перемещаемых данных, так как в противном случае операции перемещения данных будут приостановлены. Файлы нельзя перемещать, пока приложение записывает в них данные, поэтому обязательно закрывайте объекты файлов своего приложения, которые больше не нужны.</li>
<li>Локальные файлы между компьютерами не синхронизируются. Они остаются на том компьютере, где были изначально созданы.</li>
<li>Неиспользуемые временные файлы подлежат удалению. При принятии решения об удалении временного файла система учитывает такие факторы, как свободное место на диске и возраст файла.</li>
</ul>
<p>В следующих примерах кода выполняется кэширование данных на диск. Кэширование ответа сервера позволяет приложению мгновенно отображать контент после завершения его работы и повторного запуска. Для краткости в этих примерах не показано, как записывать параметры в хранилище данных приложения или реагировать на события перемещения. Эти аспекты подробно рассмотрены в <a href="http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2" target="_blank">примере данных приложения</a>.</p>
<p><strong>JavaScript</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;"><span style="color: #0000ff;">var</span> roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;<br /><span style="color: #0000ff;">var</span> filename = <span style="color: #006080;">"serverResponse.txt"</span>;<br /><br /><span style="color: #0000ff;">function</span> cacheResponse(strResponse) {<br />    roamingFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.replaceExisting)<br />        .done(<span style="color: #0000ff;">function</span> (file) {<br />            <span style="color: #0000ff;">return</span> Windows.Storage.FileIO.writeTextAsync(file, strResponse);<br />        });<br />}<br /><br /><span style="color: #0000ff;">function</span> getCachedResponse() {<br />    roamingFolder.getFileAsync(filename)<br />        .then(<span style="color: #0000ff;">function</span> (file) {<br />            <span style="color: #0000ff;">return</span> Windows.Storage.FileIO.readTextAsync(file);<br />        }).done(<span style="color: #0000ff;">function</span> (response) {<br />            print(response);<br />        }, <span style="color: #0000ff;">function</span> () {<br />            <span style="color: #008000;">// getFileAsync or readTextAsync failed. </span><br />            <span style="color: #008000;">// No cached response.</span><br />        });<br />}</pre>
</div>
</blockquote>
<p><strong>C#</strong></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="margin: 0em; padding: 0px; width: 100%; text-align: left; color: black; line-height: 12pt; overflow: visible; font-family: 'Courier New', courier, monospace; font-size: 8pt; direction: ltr; background-color: #f4f4f4;">MainPage rootPage = MainPage.Current;<br />StorageFolder roamingFolder = <span style="color: #0000ff;">null</span>;<br /><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> filename = <span style="color: #006080;">"serverResponse.txt"</span>;<br /><br />async <span style="color: #0000ff;">void</span> cacheResponse(<span style="color: #0000ff;">string</span> strResponse)<br />{<br />    StorageFile file = await roamingFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);<br />    await FileIO.WriteTextAsync(file, strResponse);<br />}<br /><br />async <span style="color: #0000ff;">void</span> getCachedResponse()<br />{<br />    <span style="color: #0000ff;">try</span><br />    {<br />        StorageFile file = await roamingFolder.GetFileAsync(filename);<br />        <span style="color: #0000ff;">string</span> response = await FileIO.ReadTextAsync(file);<br />    }<br />    <span style="color: #0000ff;">catch</span> (Exception)<br />    {<br />        <span style="color: #008000;">// getFileAsync or readTextAsync failed.</span><br />        <span style="color: #008000;">// No cached response.</span><br />    }<br />}</pre>
</div>
</blockquote>
<p>Дополнительную информацию о хранилище данных приложения можно найти в статье о <a href="http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/07/27/roaming-von-app-daten.aspx" target="_blank">перемещении данных приложения</a> и <a href="http://code.msdn.microsoft.com/windowsapps/ApplicationData-sample-fb043eb2" target="_blank">примере данных приложения</a>.</p>
<h2>Заключение</h2>
<p>Пользуйтесь приведенными здесь рекомендациями при проектировании приложений Магазина Windows, чтобы обеспечить высококачественную и беспроблемную работу с использованием сетевых подключений. Эти советы помогут упростить процесс разработки, обеспечить плавную работу ваших приложений и существенно повысить уверенность пользователей в ваших приложениях.</p>
<p>- Сухаил Халид (Suhail Khalid), руководитель программы II, Windows</p>
<p>Соавторы: Стивен Бейкер (Steven Baker) и Питер Смит (Peter Smith)</p>
<!-- Title: “Создание подключенных приложений Магазина Windows” Tags: “приложения Магазина Windows, HttpClient, подключенные приложения, XMLHTTPRequest, IXHR2, XML HTTP Request 2, WinJS.xhr” --></div>]]></content:encoded>
    </item>
    <item>
      <title>Зарегистрируйтесь для участия в конференции //build/ 2013 прямо сейчас!</title>
      <link>https://docs.microsoft.com/archive/blogs/windowsappdev_ru/113</link>
      <pubDate>Fri, 05 Apr 2013 10:34:46 GMT</pubDate>
      <dc:creator><![CDATA[Windows 8 Team]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/windowsappdev_ru/2013/04/05/113/</guid>
      <description><![CDATA[На прошлой неделе Стив Гагенхеймер (Steve Guggenheimer) объявил о проведении конференции //build/...]]></description>
      <content:encoded><![CDATA[<div class="PostContent"><p>На прошлой неделе Стив Гагенхеймер (Steve Guggenheimer) <a href="http://blogs.technet.com/b/microsoft_blog/archive/2013/03/26/announcing-build-2013.aspx" target="_blank">объявил</a> о проведении конференции //build/ 2013. Она состоится 26–28 июня 2013 года в Moscone Center в Сан-Франциско. Конференция //build/ предоставляет отличную возможность подробнее узнать о разработке приложений Магазина Windows. Программа конференции включает интересные презентации, демонстрации, информационные встречи и обсуждения, представляющие интерес для широкого круга разработчиков. Многие члены нашей рабочей группы технических специалистов прибудут в Сан-Франциско, чтобы принять участие в этих демонстрациях и ответить на ваши вопросы. Только здесь вы сможете получить новейшую и самую достоверную информацию о разработке приложений Магазина Windows. </p>  <p>Регистрация начинается сегодня, во вторник 2 апреля. Ознакомиться с более подробной информацией и зарегистрироваться для участия в конференции вы можете на сайте <a href="http://www.buildwindows.com" target="_blank">www.buildwindows.com</a>. </p>  <p>До встречи на конференции!</p> <!-- Title: “Зарегистрируйтесь для участия в конференции //build/ 2013 прямо сейчас!” Tags: “build” --></div>]]></content:encoded>
    </item>
  </channel>
</rss>