aboutsummaryrefslogtreecommitdiff
path: root/files/uk/web/javascript/reference/global_objects/promise/index.html
blob: 1f18c8bd76eb9130b657841e885b3176880c558f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
---
title: Promise
slug: Web/JavaScript/Reference/Global_Objects/Promise
tags:
  - ECMAScript 2015
  - JavaScript
  - Promise
translation_of: Web/JavaScript/Reference/Global_Objects/Promise
---
<div>{{JSRef}}</div>

<p>Об'єкт <strong><code>Promise</code></strong> відображає остаточне завершення (або неуспіх) асинхронної операції та значення, яке вона повертає.</p>

<p>Щоб дізнатись, як працюють проміси та як їх можна використовувати, радимо вам спочатку прочитати статтю <a href="/uk/docs/Web/JavaScript/Guide/Using_promises">Використання промісів</a>.</p>

<h2 id="Опис">Опис</h2>

<p><code><strong>Promise</strong></code> - це проксі для значення, яке може бути невідомим на момент створення проміса. Це дозволяє зв'язувати обробники з кінцевим успішним значенням чи причиною неуспіху асинхронних дій. Таким чином, асинхронні методи повертають значення, як синхронні методи: замість того, щоб негайно повернути кінцеве значення, асинхронний метод повертає <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>fulfilled</em>) з певним значенням, або відхиленим (<em>rejected</em>) з причиною відхилення (помилкою). Коли щось із цього відбувається, викликаються відповідні обробники, що ставляться в чергу методом об'єкта <code>then</code>. (Якщо проміс вже був виконаний чи відхилений ще до моменту приєднання відповідного обробника, то обробник буде викликаний, таким чином не відбувається "стану гонки" між завершенням асинхронної операції та приєднанням її обробників)</p>

<p>Оскільки методи <code>{{jsxref("Promise.then", "Promise.prototype.then()")}}</code> та <code>{{jsxref("Promise.catch", "Promise.prototype.catch()")}}</code> повертають проміси, їх можна з'єднувати в ланцюжки.</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/17088/promises.png" style="height: 297px; width: 801px;"></p>

<div class="note">
<p><strong>Не варто плутати з</strong><span lang="uk"><span><strong>:</strong> Декілька інших мов мають механізми лінивих обчислень та відкладених розрахунків, які також називаються "promises" - наприклад,</span> Scheme. <span>Проміси у JavaScript відображають процеси, які вже відбуваються і які можуть бути з'єднані в ланцюги з функціями зворотного виклику.</span> <span>Якщо вам потрібне ліниве обчислення виразу, розгляньте </span></span><a href="/uk/docs/Web/JavaScript/Reference/Functions/Стрілкові_функції">стрілкові функції</a><span lang="uk"><span> без аргументів: <code>f = () =&gt; вираз</code> для створення лінивого виразу, та <code>f()</code> для обчислення.</span></span></p>
</div>

<div class="note">
<p><strong>Заувага</strong>: Проміс називають <em>встановленим</em> (<em>settled)</em>, якщо він або виконаний, або відхилений, але не знаходиться у стані очікування. Ви також почуєте термін <em>вирішений</em> (<em>resolved</em>) щодо промісів - він означає, що проміс встановлений, або ж "зафіксований", щоб відповідати стану іншого проміса. Стаття <a href="https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md">States and Fates</a> містить більше подробиць щодо термінології промісів.</p>
</div>

<h2 id="Конструктор">Конструктор</h2>

<dl>
 <dt><code><a href="/uk/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise">Promise()</a></code></dt>
 <dd>Конструктор переважно використовується для загортання функцій, які самі не підтримують проміси.</dd>
</dl>

<h2 id="Властивості">Властивості</h2>

<dl>
 <dt><code>Promise.length</code></dt>
 <dd><span id="result_box" lang="uk"><span>Значення довжини, завжди дорівнює 1 (кількість аргументів конструктора)</span></span>.</dd>
 <dt><code>Promise.prototype</code></dt>
 <dd>Прототип для конструктора <code>Promise</code>.</dd>
</dl>

<h2 id="Методи">Методи</h2>

<dl>
 <dt>{{jsxref("Promise.all", "Promise.all(iterable)")}}</dt>
 <dd>Чекає, доки усі проміси не будуть вирішені, або поки будь-який з промісів не буде відхилений.</dd>
 <dd><span id="result_box" lang="uk"><span>Якщо повернений проміс вирішується, він вирішується із сукупним масивом значень вирішених промісів, у тому ж порядку, в якому вони визначені в ітерабельному об'єкті промісів.</span> </span></dd>
 <dd><span lang="uk"><span>В разі відхилення, він відхиляється з причиною з першого відхиленого проміса у ітерабельному об'єкті.</span></span></dd>
 <dt>{{JSxRef("Promise.allSettled", "Promise.allSettled(iterable)")}}</dt>
 <dd>Чекає, доки усі проміси не будуть встановлені (кожен має бути або вирішений, або відхилений).</dd>
 <dd>Повертає проміс, який вирішується після того, як усі надані проміси були або вирішені, або відхилені, з масивом об'єктів, які описують результат кожного проміса.</dd>
 <dt>{{jsxref("Promise.race", "Promise.race(iterable)")}}</dt>
 <dd>Чекає, доки будь-який з промісів не буде або вирішений, або відхилений.</dd>
 <dd>Якщо повернений проміс вирішений, він вирішується зі значенням першого проміса з ітерабельного об'єкта, який був вирішений.</dd>
 <dd><span id="result_box" lang="uk"><span>Якщо він відхилений, він відхиляється з причиною першого відхиленого проміса.</span></span></dd>
</dl>

<dl>
 <dt>{{jsxref("Promise.відхилено", "Promise.reject(reason)")}}</dt>
 <dd>Повертає новий об'єкт <code>Promise</code>, відхилений з наданою причиною.</dd>
</dl>

<dl>
 <dt>{{jsxref("Promise.resolve", "Promise.resolve(value)")}}</dt>
 <dd><span id="result_box" lang="uk"><span>Повертає новий об'єкт <code>Promise</code>, який вирішується з наданим значенням.</span> <span>Якщо значенням є промісоподібний об'єкт (такий, що має метод <code>then</code>), то повернений проміс буде його "дотримуватись", приймаючи його кінцевий стан; у іншому випадку повернений проміс буде виконаний з наданим значенням</span><span>.</span></span></dd>
 <dd>Загалом, якщо ви не знаєте, є значення промісом чи ні, використайте {{JSxRef("Promise.resolve", "Promise.resolve(value)")}} та працюйте з поверненим значенням як з промісом.</dd>
</dl>

<h2 id="Прототип_Promise">Прототип Promise</h2>

<h3 id="Властивості_2">Властивості</h3>

<dl>
 <dt><code>Promise.prototype.constructor</code></dt>
 <dd>Вертає функцію, яка створила прототип екземпляра. Це за замовчуванням функція {{jsxref("Promise")}}.</dd>
</dl>

<h3 id="Методи_2">Методи</h3>

<dl>
 <dt>{{jsxref("Promise.prototype.catch()")}}</dt>
 <dd>Додає до проміса функцію зворотного виклику для обробки відхилення та вертає новий проміс, що вирішується з поверненим значенням цієї функції, коли вона викликається, або з початковим значенням виконання, якщо проміс, навпаки, виконається.</dd>
 <dt>{{jsxref("Promise.prototype.then()")}}</dt>
 <dd>Додає до проміса обробники виконання та відхилення та вертає новий проміс, що вирішується з поверненим значенням обробника, який викликався, або з початковим встановленим значенням, якщо проміс не оброблявся (тобто, якщо відповідний обробник <code>onFulfilled</code> чи <code>onRejected</code> не є функцією).</dd>
 <dt>{{jsxref("Promise.prototype.finally()")}}</dt>
 <dd>Додає до проміса обробник та вертає новий проміс, який вирішується, коли вирішується початковий проміс. Обробник викликається, коли проміс встановлений, тобто, або виконаний, або відхилений.</dd>
</dl>

<h2 id="Приклади">Приклади</h2>

<h3 id="Базовий_приклад">Базовий приклад</h3>

<pre class="brush: js">let myFirstPromise = new Promise((resolve, reject) =&gt; {
  // Викликаємо resolve(...), коли те, що ми робили асинхронно, успішно виконалось, і reject(...), якщо неуспішно.
  // В цьому прикладі ми використовуємо setTimeout(...) для симуляції асинхронного коду.
  // В житті ви, ймовірно, використовуватиме щось на кшталт XHR або HTML5 API.
  setTimeout( function() {
    resolve("Успіх!")  // Є! Все пройшло добре!
  }, 250)
})

myFirstPromise.then((successMessage) =&gt; {
  // successMessage - це те, що ми передаємо у наведену вище функцію resolve(...).
  // Це не обов'язково має бути рядок, але, якщо це повідомлення про успіх, то, мабуть, це буде він.
  console.log("Є! " + successMessage)
});</pre>

<h3 id="Ускладнений_приклад">Ускладнений приклад</h3>

<div class="hidden">
<pre class="brush: html">&lt;button id="btn"&gt;Зробити проміс!&lt;/button&gt;
&lt;div id="log"&gt;&lt;/div&gt;</pre>
</div>

<p>Цей маленький приклад демонструє механізм об'єкта <code>Promise</code>. Метод <code>testPromise()</code> викликається кожний раз, коли натискається кнопка <a href="/uk/docs/Web/HTML/Element/button" title="The HTML &lt;button> element represents a clickable button, used to submit forms or anywhere in a document for accessible, standard button functionality."><code>&lt;button&gt;</code></a>. Він створює проміс, який буде виконаний з використанням <a href="/uk/docs/Web/API/Window/setTimeout" title="REDIRECT WindowTimers.setTimeout"><code>window.setTimeout()</code></a> з лічильником проміса (число, що стартує від 1) кожні 1-3 секунди, у випадковому порядку. Конструктор <code>Promise()</code> використовується для створення проміса.</p>

<p>Виконання проміса логується просто, виконанням зворотного виклику через {{jsxref("Promise.prototype.then()","p1.then()")}}. Кілька логів демонструють, як синхронна частина методу відокремлюється від асинхронного завершення проміса.</p>

<pre class="brush: js">'use strict';
var promiseCount = 0;

function testPromise() {
    var thisPromiseCount = ++promiseCount;

    var log = document.getElementById('log');
    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Запуск (&lt;small&gt;Синхронний код запущено&lt;/small&gt;)&lt;br/&gt;');

    // Створюємо новий проміс: ми передаємо лічильник цього проміса, починаючи з 1 (після очікування 3с)
    var p1 = new Promise(
        // Функція вирішення викликається з можливістю вирішити або
        // відхилити проміс
        function(resolve, reject) {
            log.insertAdjacentHTML('beforeend', thisPromiseCount +
                ') Запуск проміса (&lt;small&gt;Асинхронний код запущено&lt;/small&gt;)&lt;br/&gt;');
            // Це лише приклад для створення асинхронності
            window.setTimeout(
                function() {
                    // Ми виконуємо проміс!
                    resolve(thisPromiseCount);
                }, Math.random() * 2000 + 1000);
        }
    );

    // Визначаємо, що робити, коли проміс вирішено/виконано, викликом then(),
    // а метод catch() визначає, що робити, якщо проміс відхилено.
    p1.then(
        // Залогувати значення виконання
        function(val) {
            log.insertAdjacentHTML('beforeend', val +
                ') Проміс виконано (&lt;small&gt;Асинхронний код завершений&lt;/small&gt;)&lt;br/&gt;');
        })
    .catch(
        // Залогувати причину відхилення
        function(reason) {
            console.log('Обробити тут відхилений проміс ('+reason+').');
        });

    log.insertAdjacentHTML('beforeend', thisPromiseCount +
        ') Проміс створено (&lt;small&gt;Синхронний код завершений&lt;/small&gt;)&lt;br/&gt;');
}
</pre>

<div class="hidden">
<pre class="brush: js">if ("Promise" in window) {
  var btn = document.getElementById("btn");
  btn.addEventListener("click",testPromise);
} else {
  log = document.getElementById('log');
  log.innerHTML = "Живий приклад недоступний, оскільки ваш переглядач не підтримує інтерфейс об'єктів &lt;code&gt;Promise&lt;code&gt;.";
}</pre>
</div>

<p>Цей приклад починається натисканням кнопки. Вам потрібен переглядач, що підтримує об'єкти <code>Promise</code>. Натиснувши кнопку кілька разів за короткий відрізок часу, ви навіть побачите, як різні проміси виконуються один після іншого.</p>

<p>{{EmbedLiveSample("Ускладнений_приклад", "500", "200")}}</p>

<h2 id="Завантаження_зображення_за_допомогою_XHR">Завантаження зображення за допомогою XHR</h2>

<p>Інший простий приклад використання об'єктів <code>Promise</code> та <code><a href="/uk/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> - для завантаження зображення - доступний у репозиторії <a href="https://github.com/mdn/js-examples/tree/master/promises-test">promise-test</a> на MDN 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">Specification</th>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}</td>
  </tr>
 </tbody>
</table>

<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2>

<p class="hidden">To contribute to this compatibility data, please write a pull request against this file: <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a>.</p>

<p>{{Compat("javascript.builtins.Promise")}}</p>

<h2 id="Див._також">Див. також</h2>

<ul>
 <li><a href="/uk/docs/Web/JavaScript/Guide/Using_promises">Використання промісів</a></li>
 <li><a href="http://promisesaplus.com/">Promises/A+ specification</a></li>
 <li><a href="https://medium.com/@ramsunvtech/promises-of-promise-part-1-53f769245a53">Venkatraman.R - JS Promise (Part 1, Basics)</a></li>
 <li><a href="https://medium.com/@ramsunvtech/js-promise-part-2-q-js-when-js-and-rsvp-js-af596232525c#.dzlqh6ski">Venkatraman.R - JS Promise (Part 2 - Using Q.js, When.js and RSVP.js)</a></li>
 <li><a href="https://tech.io/playgrounds/11107/tools-for-promises-unittesting/introduction">Venkatraman.R - Tools for Promises Unit Testing</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 Patterns 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="https://github.com/anonyco/SPromiseMeSpeedJS/blob/master/README.md">Speed-polyfill to polyfill both promise availability and promise performance.</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>