diff options
Diffstat (limited to 'files/ru/web/javascript/reference/global_objects/promise/index.html')
-rw-r--r-- | files/ru/web/javascript/reference/global_objects/promise/index.html | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/files/ru/web/javascript/reference/global_objects/promise/index.html b/files/ru/web/javascript/reference/global_objects/promise/index.html new file mode 100644 index 0000000000..c4577ab151 --- /dev/null +++ b/files/ru/web/javascript/reference/global_objects/promise/index.html @@ -0,0 +1,267 @@ +--- +title: Promise +slug: Web/JavaScript/Reference/Global_Objects/Promise +tags: + - ECMAScript6 + - JavaScript + - Promise + - Обещания +translation_of: Web/JavaScript/Reference/Global_Objects/Promise +--- +<div>{{JSRef}}</div> + +<h2 id="Сводка">Сводка</h2> + +<p>Объект <strong><code>Promise</code></strong> (промис) используется для отложенных и асинхронных вычислений.</p> + +<p>{{EmbedInteractiveExample("pages/js/promise-constructor.html")}}</p> + +<div class="hidden"> +<p>Исходники интерактивного демо находятся в репозитории на GitHub. Если вы хотите внести свой вклад в развитие интерактивных демо, пожалуйста, склонируйте <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> и отправьте нам пулреквест.</p> +</div> + +<h2 id="Синтаксис">Синтаксис</h2> + +<pre class="brush: js">new Promise(<em>executor</em>); +new Promise(function(resolve, reject) { ... });</pre> + +<h3 id="Параметры">Параметры</h3> + +<dl> + <dt>executor</dt> + <dd>Объект функции с двумя аргументами <code>resolve</code> и <code>reject</code>. Функция <code>executor</code> получает оба аргумента и выполняется сразу, еще до того как конструктор вернет созданный объект. Первый аргумент (<code>resolve</code>) вызывает успешное исполнение промиса, второй (<code>reject</code>) отклоняет его.<br> + Обычно функция <code>executor</code> описывает выполнение какой-то асинхронной работы, по завершении которой необходимо вызвать функцию <code>resolve</code> или <code>reject</code>. Обратите внимание, что возвращаемое значение функции <code>executor</code> игнорируется.</dd> +</dl> + +<h2 id="Описание">Описание</h2> + +<p>Интерфейс <code><strong>Promise</strong></code> (промис) представляет собой обертку для значения, неизвестного на момент создания промиса. Он позволяет обрабатывать результаты асинхронных операций так, как если бы они были синхронными: вместо конечного результата асинхронного метода возвращается <em>обещание </em>(промис)<em> </em>получить результат в некоторый момент в будущем.</p> + +<p><code>Promise</code> может находиться в трёх состояниях:</p> + +<ul> + <li><em>ожидание (pending)</em>: начальное состояние, не исполнен и не отклонен.</li> + <li><em>исполнено (fulfilled)</em>: операция завершена успешно.</li> + <li><em>отклонено (rejected)</em>: операция завершена с ошибкой.</li> +</ul> + +<p>При создании промис находится в <em>ожидании (pending)</em>, а затем может стать <em>исполненным </em> (<em>fulfilled)</em>, вернув полученный результат (значение), или <em>отклоненным </em>(<em>rejected),</em> вернув причину отказа. В любом из этих случаев вызывается обработчик, прикрепленный к промису методом <code>then</code>. (Если в момент назначения обработчика промис уже исполнен или отклонен, обработчик все равно будет вызван, т.е. асинхронное исполнение промиса и назначение обработчика не будет происходить в «состоянии гонки», как, например, в случае с событиями в DOM.)</p> + +<p>Так как методы <code>{{JSxRef("Promise.then", "Promise.prototype.then()")}}</code> и <code>{{JSxRef("Promise.catch", "Promise.prototype.catch()")}}</code> сами возвращают промис, их можно вызывать цепочкой, создавая <em>соединения.</em></p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/8633/promises.png" style="height: 297px; width: 801px;"></p> + +<div class="blockIndicator note"> +<p><strong>Примечание:</strong> говорят, что промис находится в состоянии <em>завершен (settled) </em>когда он или исполнен или отклонен, т.е. в любом состоянии, кроме ожидания (это лишь форма речи, не являющаяся настоящим состоянием промиса). Также можно встретить термин <em>исполен (resolved) </em>— это значит что промис <em>завершен </em>или "заблокирован" в ожидании завершения другого промиса. В статье <a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">состояния и fates</a> приводится более подробное описание терминологии.</p> +</div> + +<h2 id="Свойства">Свойства</h2> + +<dl> + <dt><code>Promise.length</code></dt> + <dd>Значение свойства всегда равно 1 (количество аргументов конструктора).</dd> + <dt>{{jsxref("Promise.prototype")}}</dt> + <dd>Представляет прототип для конструктора <code>Promise</code>.</dd> +</dl> + +<h2 id="Методы">Методы</h2> + +<dl> + <dt>{{jsxref("Promise.all", "Promise.all(iterable)")}}</dt> + <dd>Ожидает исполнения всех промисов или отклонения любого из них.</dd> + <dd>Возвращает промис, который исполнится после исполнения всех промисов в <code>iterable</code>. В случае, если любой из промисов будет отклонен, <code>Promise.all</code> будет также отклонен.</dd> + <dt>{{JSxRef("Promise.allSettled", "Promise.allSettled(iterable)")}}</dt> + <dd>Ожидает завершения всех полученных промисов (как исполнения так и отклонения).</dd> + <dd>Возвращает промис, который исполняется когда все полученные промисы завершены (исполнены или отклонены), содержащий массив результатов исполнения полученных промисов.</dd> + <dt>{{jsxref("Promise.race", "Promise.race(iterable)")}}</dt> + <dd>Ожидает исполнения или отклонения любого из полученных промисов.</dd> + <dd>Возвращает промис, который будет исполнен или отклонен с результатом исполнения первого исполненного или отклонённого промиса из .<code>iterable</code>.</dd> +</dl> + +<dl> + <dt>{{jsxref("Promise.reject", "Promise.reject(reason)")}}</dt> + <dd>Возвращает промис, отклонённый из-за <code>reason</code>.</dd> +</dl> + +<dl> + <dt>{{jsxref("Promise.resolve", "Promise.resolve(value)")}}</dt> + <dd>Возвращает промис, исполненный с результатом <code>value</code>.</dd> + <dd> + <div class="hidden"> + <p>Если у <code>value</code> имеется метод <code>then</code>, то возвращаемый промис будет "следовать" продолжению, выступая адаптером его состояния; в противном случае будет возвращен промис в исполненном состоянии. Если вы не уверены, является ли некоторое значение промисом, вы можете обернуть его в {{JSxRef("Promise.resolve", "Promise.resolve(value)")}} и продолжить работу с ним как с промисом.</p> + </div> + </dd> +</dl> + +<h2 id="Прототип_Promise">Прототип <code>Promise</code></h2> + +<h3 id="Свойства_2">Свойства</h3> + +<p>{{page('ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Свойства')}}</p> + +<h3 id="Методы_2">Методы</h3> + +<p>{{page('ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/prototype','Методы')}}</p> + +<h2 id="Создание_промиса">Создание промиса</h2> + +<p>Объект <code>Promise</code> создается при помощи ключевого слова <code>new</code> и своего конструктора. Конструктор <code>Promise</code> принимает в качестве аргумента функцию, называемую "исполнитель" (<em>executor function</em>). Эта функция должна принимать две функции-коллбэка в качестве параметров. Первый из них (<code>resolve</code>) вызывается, когда асинхронная операция завершилась успешно и вернула результат своего исполнения в виде значения. Второй коллбэк (<code>reject</code>) вызывается, когда операция не удалась, и возвращает значение, указывающее на причину неудачи, чаще всего объект ошибки.</p> + +<pre class="brush: js">const myFirstPromise = new Promise((resolve, reject) => { + // выполняется асинхронная операция, которая в итоге вызовет: + // + // resolve(someValue); // успешное завершение + // или + // reject("failure reason"); // неудача +});</pre> + +<p>Чтобы снабдить функцию функционалом обещаний, нужно просто вернуть в ней объект <code>Promise</code>:</p> + +<pre class="brush: js">function myAsyncFunction(url) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = () => resolve(xhr.responseText); + xhr.onerror = () => reject(xhr.statusText); + xhr.send(); + }); +}</pre> + +<h2 id="Примеры">Примеры</h2> + +<h3 id="Простой_пример">Простой пример</h3> + +<pre class="brush: html" style="display: none;">Создать промис! +</pre> + +<pre class="brush: js">let myFirstPromise = new Promise((resolve, reject) => { + // Мы вызываем resolve(...), когда асинхронная операция завершилась успешно, и reject(...), когда она не удалась. + // В этом примере мы используем setTimeout(...), чтобы симулировать асинхронный код. + // В реальности вы, скорее всего, будете использовать XHR, HTML5 API или что-то подобное. + setTimeout(function(){ + resolve("Success!"); // Ура! Всё прошло хорошо! + }, 250); +}); + +myFirstPromise.then((successMessage) => { + // successMessage - это что угодно, что мы передали в функцию resolve(...) выше. + // Это необязательно строка, но если это всего лишь сообщение об успешном завершении, это наверняка будет она. + console.log("Ура! " + successMessage); +});</pre> + +<h3 id="Продвинутый_пример">Продвинутый пример</h3> + +<pre class="brush: html" style="display: none;">Создать промис! +</pre> + +<div id="log"> +<pre class="brush: html"><button id="btn">Создать Promise!</button> +<div id="log"></div></pre> +</div> + +<p>Данный небольшой пример показывает механизм работы с <code>Promise</code>. Метод <code>testPromise()</code> вызывается при каждом нажатии на {{HTMLElement("button")}}. При этом создаётся промис, которое успешно выполняется при помощи <code>window.setTimeout</code>, со значением <code>'result'</code> в случайном интервале от 1 до 3-х секунд.</p> + +<p>исполнение промиса протоколируется при помощи продолжения <code>p1.then</code>. Это показывает как синхронная часть метода отвязана от асинхронного завершения промиса.</p> + +<pre class="brush: js">var promiseCount = 0; +function testPromise() { + var thisPromiseCount = ++promiseCount; + + var log = document.getElementById('log'); + log.insertAdjacentHTML('beforeend', thisPromiseCount + + ') Запуск (запуск синхронного кода) +'); + + // Создаём промис, возвращающее 'result' (по истечении 3-х секунд) + var p1 = new Promise( + // Функция разрешения позволяет завершить успешно или + // отклонить промис + function(resolve, reject) { + log.insertAdjacentHTML('beforeend', thisPromiseCount + + ') Запуск промиса (запуск асинхронного кода) +'); + // Это всего лишь пример асинхронности + window.setTimeout( + function() { + // Обещание исполнено! + resolve(thisPromiseCount) + }, Math.random() * 2000 + 1000); + }); + + // Указываем, что сделать с исполненным промисм + p1.then( + // Записываем в протокол + function(val) { + log.insertAdjacentHTML('beforeend', val + + ') Обещание исполнено (асинхронный код завершён) +'); + }); + + log.insertAdjacentHTML('beforeend', thisPromiseCount + + ') Обещание создано (синхронный код завершён) +'); +} +</pre> + +<pre class="brush:js" style="display: none;">if ("Promise" in window) { + btn = document.getElementById("btn"); + btn.addEventListener("click",testPromise); +} +else { + log = document.getElementById('log'); + log.innerHTML = "Live example not available as your browser doesn't support the Promise interface."; +} +</pre> + +<pre class="brush: js">if ("Promise" in window) { + let btn = document.getElementById("btn"); + btn.addEventListener("click",testPromise); +} else { + log = document.getElementById('log'); + log.innerHTML = "Демонстрация невозможна, поскольку ваш браузер не поддерживает интерфейс <code>Promise<code>."; +}</pre> + +<p>Данный пример запускается при нажатии на кнопку. Для этого вам необходим браузер, поддерживающий <code>Promise</code>. При последовательных нажатиях на кнопку с коротким интервалом, вы можете увидеть как различные промиса будут исполнены один за другим.</p> + +<h3 id="Загрузка_изображения_при_помощи_XHR">Загрузка изображения при помощи XHR</h3> + +<p>Другой простой пример использования <code>Promise</code> и <code><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> для загрузки изображения доступен в репозитории MDN<a href="https://github.com/mdn/js-examples/tree/master/promises-test">promise-test</a> на GitHub. Вы также можете <a href="https://mdn.github.io/js-examples/promises-test/">посмотреть его в действии</a>. Каждый шаг прокомментирован и вы можете подробно исследовать Promise и XHR.</p> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификация</th> + <th scope="col">Статус</th> + <th scope="col">Комментарий</th> + </tr> + <tr> + <td><a href="https://github.com/domenic/promises-unwrapping">domenic/promises-unwrapping</a></td> + <td>Черновик</td> + <td>Начало работы над стандартом.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-promise-objects', 'Promise')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Изначальное определение в стандарте ECMA.</td> + </tr> + </tbody> +</table> + +<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2> + +<p>{{Compat("javascript.builtins.Promise")}}</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li><a href="http://promisesaplus.com/">Спецификация Promises/A+</a></li> + <li><a href="http://www.html5rocks.com/en/tutorials/es6/promises/">Jake Archibald: JavaScript Promises: There and Back Again</a></li> + <li><a href="http://de.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript">Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Pattern in JavaScript</a></li> + <li><a href="http://www.mattgreer.org/articles/promises-in-wicked-detail/">Matt Greer: JavaScript Promises ... In Wicked Detail</a></li> + <li><a href="https://www.promisejs.org/">Forbes Lindesay: promisejs.org</a></li> + <li><a href="http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nolan Lawson: We have a problem with promises — Common mistakes with promises</a></li> + <li><a href="https://github.com/jakearchibald/es6-promise/">Promise polyfill</a></li> + <li><a href="https://www.udacity.com/course/javascript-promises--ud898">Udacity: JavaScript Promises</a></li> +</ul> |