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) |