175 lines
9.0 KiB
Markdown
175 lines
9.0 KiB
Markdown
---
|
||
title: Promises
|
||
localeTitle: обещания
|
||
---
|
||
## обещания
|
||
|
||
JavaScript однопоточный, что означает, что два бита скрипта не могут работать одновременно; они должны бежать один за другим. Promise - это объект, который представляет собой возможное завершение (или отказ) асинхронной операции и ее итоговое значение.
|
||
|
||
```javascript
|
||
var promise = new Promise(function(resolve, reject) {
|
||
// do thing, then…
|
||
|
||
if (/* everything worked */) {
|
||
resolve("See, it worked!");
|
||
}
|
||
else {
|
||
reject(Error("It broke"));
|
||
}
|
||
});
|
||
```
|
||
|
||
## В одном из этих состояний существует обещание
|
||
|
||
* Ожидание: начальное состояние, ни выполнено, ни отклонено.
|
||
* Выполнено: операция успешно завершена.
|
||
* Отклонено: операция завершилась неудачно.
|
||
|
||
Объект Promise работает как прокси-сервер для значения, которое не обязательно известно при создании обещания. Это позволяет связать обработчики с вероятным результатом успешной асинхронной операции или причиной сбоя. Это позволяет асинхронным методам возвращать такие значения, как синхронные методы: вместо немедленного возврата окончательного значения асинхронный метод возвращает обещание предоставить значение в какой-то момент в будущем.
|
||
|
||
## Использование 'Then' (Promise Chaining)
|
||
|
||
Чтобы выполнить несколько асинхронных вызовов и синхронизировать их один за другим, вы можете использовать цепочку слияния. Это позволяет использовать значение из первого обещания в последующих последующих обратных вызовах.
|
||
|
||
```javascript
|
||
Promise.resolve('some')
|
||
.then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some')
|
||
return new Promise(function(resolve, reject) {
|
||
setTimeout(function() {
|
||
string += 'thing';
|
||
resolve(string);
|
||
}, 1);
|
||
});
|
||
})
|
||
.then(function(string) { // <-- This will happen after the above .then's new Promise resolves
|
||
console.log(string); // <-- Logs 'something' to the console
|
||
});
|
||
```
|
||
|
||
## API обещаний
|
||
|
||
В классе Promise существует 4 статических метода:
|
||
|
||
* Promise.resolve
|
||
* Promise.reject
|
||
* Promise.all
|
||
* Promise.race
|
||
|
||
## Обещания могут быть соединены вместе
|
||
|
||
При написании обещаний для решения конкретной проблемы вы можете связать их вместе, чтобы сформировать логику.
|
||
|
||
```javascript
|
||
var add = function(x, y) {
|
||
return new Promise((resolve,reject) => {
|
||
var sum = x + y;
|
||
if (sum) {
|
||
resolve(sum);
|
||
}
|
||
else {
|
||
reject(Error("Could not add the two values!"));
|
||
}
|
||
});
|
||
};
|
||
|
||
var subtract = function(x, y) {
|
||
return new Promise((resolve, reject) => {
|
||
var sum = x - y;
|
||
if (sum) {
|
||
resolve(sum);
|
||
}
|
||
else {
|
||
reject(Error("Could not subtract the two values!"));
|
||
}
|
||
});
|
||
};
|
||
|
||
// Starting promise chain
|
||
add(2,2)
|
||
.then((added) => {
|
||
// added = 4
|
||
return subtract(added, 3);
|
||
})
|
||
.then((subtracted) => {
|
||
// subtracted = 1
|
||
return add(subtracted, 5);
|
||
})
|
||
.then((added) => {
|
||
// added = 6
|
||
return added * 2;
|
||
})
|
||
.then((result) => {
|
||
// result = 12
|
||
console.log("My result is ", result);
|
||
})
|
||
.catch((err) => {
|
||
// If any part of the chain is rejected, print the error message.
|
||
console.log(err);
|
||
});
|
||
```
|
||
|
||
Это полезно для использования парадигмы _функционального программирования_ . Создавая функции для манипулирования данными, вы можете объединить их вместе, чтобы собрать окончательный результат. Если в любой точке цепочки функций значение _отклоняется,_ цепь перейдет к ближайшему обработчику `catch()` .
|
||
|
||
Для получения дополнительной информации о функциональном программировании: [функциональное программирование](https://en.wikipedia.org/wiki/Functional_programming)
|
||
|
||
## Генераторы функций
|
||
|
||
В последних выпусках JavaScript ввел больше способов изначально обрабатывать обещания. Одним из таких способов является генератор функций. Генераторы функций являются «правдоподобными» функциями. При использовании с Promise генераторы могут сделать использование намного проще для чтения и появиться «синхронно».
|
||
|
||
```javascript
|
||
const myFirstGenerator = function* () {
|
||
const one = yield 1;
|
||
const two = yield 2;
|
||
const three = yield 3;
|
||
|
||
return 'Finished!';
|
||
}
|
||
|
||
const gen = myFirstGenerator();
|
||
```
|
||
|
||
Вот наш первый генератор, который вы можете видеть по синтаксису `function*` . Объявленная переменная `gen` не будет запускать `myFirstGenerator` , но вместо этого «этот генератор будет готов к использованию».
|
||
|
||
```javascript
|
||
console.log(gen.next());
|
||
// Returns { value: 1, done: false }
|
||
```
|
||
|
||
Когда мы запустим `gen.next()` он отключит генератор и продолжит работу. Поскольку это первый раз, когда мы вызвали `gen.next()` он будет работать с `yield 1` и приостанавливаться до тех пор, пока мы снова не назовем `gen.next()` . Когда вызывается `yield 1` , он возвращает нам `value` которое было получено, и независимо от того, `done` ли генератор.
|
||
|
||
```javascript
|
||
console.log(gen.next());
|
||
// Returns { value: 2, done: false }
|
||
|
||
console.log(gen.next());
|
||
// Returns { value: 3, done: false }
|
||
|
||
console.log(gen.next());
|
||
// Returns { value: 'Finished!', done: true }
|
||
|
||
console.log(gen.next());
|
||
// Will throw an error
|
||
```
|
||
|
||
Поскольку мы продолжаем называть `gen.next()` он будет продолжать идти на следующий `yield` и приостанавливать каждый раз. После того, как у вас больше нет `yield` , он продолжит работу с остальной частью генератора, которая в этом случае просто вернется `'Finished!'` , Если вы снова вызове `gen.next()` , он будет генерировать ошибку по завершении работы генератора.
|
||
|
||
Теперь представьте, что если каждый `yield` в этом примере был `Promise` , сам код выглядел бы крайне синхронно.
|
||
|
||
### Promise.all (iterable) очень полезен для множественного запроса к другому источнику
|
||
|
||
Метод Promise.all (iterable) возвращает единственное обещание, которое разрешает, когда все обещания в итерабельном аргументе разрешены или когда аргумент итерации не содержит никаких обещаний. Он отвергает причину первого обещания, которое отвергает.
|
||
|
||
```javascript
|
||
var promise1 = Promise.resolve(catSource);
|
||
var promise2 = Promise.resolve(dogSource);
|
||
var promise3 = Promise.resolve(cowSource);
|
||
|
||
Promise.all([promise1, promise2, promise3]).then(function(values) {
|
||
console.log(values);
|
||
});
|
||
// expected output: Array ["catData", "dogData", "cowData"]
|
||
```
|
||
|
||
### Больше информации
|
||
|
||
Для получения дополнительной информации о обещаниях: [обещания](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) |