ES6 - Обещания

Синтаксис обещаний

Синтаксис, связанный с обещанием, упомянут ниже, где, p это объект обещания, resolve - это функция, которая должна вызываться при успешном выполнении обещания и reject - это функция, которую следует вызывать, когда промис обнаруживает ошибку.

let p = new Promise(function(resolve,reject){
   let workDone = true; // some time consuming work
      if(workDone){
      //invoke resolve function passed
      
	  resolve('success promise completed')
   }
   else{
      reject('ERROR , work could not be completed')
   }
})

пример

В приведенном ниже примере показана функция add_positivenos_async()который добавляет два числа асинхронно. Обещание разрешается, если переданы положительные значения. Обещание отклоняется, если переданы отрицательные значения.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed') 
         })
         return p;
   }

   add_positivenos_async(10, 20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   add_positivenos_async(-10, -20)
      .then(successHandler) // if promise resolved
      .catch(errorHandler);// if promise rejected

   function errorHandler(err) {
      console.log('Handling error', err)
   }
   function successHandler(result) {
      console.log('Handling success', result)
   }

   console.log('end')
</script>

Вывод приведенного выше кода будет таким, как указано ниже -

end
Handling success 30
Handling error NOT_Postive_Number_Passed

Цепочка обещаний

Promises chaining можно использовать, когда у нас есть последовательность asynchronous tasksделать одно за другим. Обещания связаны, когда обещание зависит от результата другого обещания. Это показано в примере ниже.

пример

В приведенном ниже примере add_positivenos_async() functionдобавляет два числа асинхронно и отклоняет, если переданы отрицательные значения. Результат текущего вызова асинхронной функции передается в качестве параметра последующим вызовам функции. Обратите внимание на каждуюthen() метод имеет оператор возврата.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })
      return p;
   }

   add_positivenos_async(10,20)
   .then(function(result){
      console.log("first result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
   console.log("second result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
      console.log("third result",result)
   })

   console.log('end')
</script>

Вывод приведенного выше кода будет таким, как указано ниже -

end
first result 30
second result 60
third result 120

Некоторые часто используемые методы объекта обещания подробно обсуждаются ниже:

обещание.all ()

Этот метод может быть полезен для агрегирования результатов нескольких обещаний.

Синтаксис

Синтаксис для promise.all() метод упомянут ниже, где, iterable- итеративный объект. Например, массив.

Promise.all(iterable);

пример

В приведенном ниже примере выполняется массив асинхронных операций. [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]. Когда все операции завершены, обещание полностью разрешено.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }
   //Promise.all(iterable)

Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)])
   .then(function(resolveValue){
      console.log(resolveValue[0])
      console.log(resolveValue[1])
      console.log(resolveValue[2])
      console.log('all add operations done')
   })
   .catch(function(err){
      console.log('Error',err)
   })
   console.log('end')
</script>

Вывод приведенного выше кода будет следующим:

end
30
70
110
all add operations done

обещание.race ()

Эта функция принимает массив обещаний и возвращает первое выполненное обещание.

Синтаксис

Синтаксис для promise.race()Функция упоминается ниже, где iterable - это итеративный объект. Например, массив.

Promise.race(iterable)

пример

В приведенном ниже примере используется массив [add_positivenos_async(10,20),add_positivenos_async(30,40)] асинхронных операций.

Обещание разрешается всякий раз, когда завершается любая из операций добавления. Обещание не будет ждать завершения других асинхронных операций.

<script>   
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
            //do some complex time consuming work
            resolve(n1 + n2)
         } else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }

   //Promise.race(iterable)
   Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)])
   .then(function(resolveValue){
      console.log('one of them is done')
      console.log(resolveValue)
   }).catch(function(err){
      console.log("Error",err)
   })

   console.log('end')
</script>

Вывод приведенного выше кода будет следующим:

end
one of them is done
30

Promises- это чистый способ реализации асинхронного программирования в JavaScript (новая функция ES6). До обещаний обратные вызовы использовались для реализации асинхронного программирования. Начнем с понимания того, что такое асинхронное программирование и его реализация с использованием обратных вызовов.

Понимание обратного вызова

Функция может быть передана в качестве параметра другой функции. Этот механизм получил названиеCallback. Обратный звонок будет полезен в событиях.

Следующий пример поможет нам лучше понять эту концепцию.

<script>   
   function notifyAll(fnSms, fnEmail) {   
      console.log('starting notification process');   
      fnSms();   
      fnEmail();   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   }, 
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); 
   //executes last or blocked by other methods   
</script>

в notifyAll()способ, показанный выше, уведомление происходит путем отправки SMS и электронной почты. Следовательно, вызывающий метод notifyAll должен передать две функции в качестве параметров. Каждая функция берет на себя отдельную ответственность, например, отправка SMS и отправка электронной почты.

Следующий вывод отображается при успешном выполнении вышеуказанного кода.

starting notification process 
Sms send .. 
Email send .. 
End of script

В коде, упомянутом выше, вызовы функций синхронны. Это означает, что поток пользовательского интерфейса будет ждать завершения всего процесса уведомления. Синхронные вызовы становятся блокирующими вызовами. Давайте теперь разберемся с неблокирующими или асинхронными вызовами.

Понимание AsyncCallback

Рассмотрим приведенный выше пример.

Чтобы включить скрипт, выполните асинхронный или неблокирующий вызов метода notifyAll (). Мы будем использоватьsetTimeout()метод JavaScript. По умолчанию этот метод является асинхронным.

Метод setTimeout () принимает два параметра:

  • Функция обратного вызова.

  • Количество секунд, по истечении которых будет вызван метод.

В этом случае процесс уведомления был завершен тайм-аутом. Следовательно, это займет двухсекундную задержку, установленную кодом. Будет вызвана функция notifyAll (), и основной поток будет выполняться, как и другие методы. Следовательно, процесс уведомления не будет блокировать основной поток JavaScript.

<script>   
   function notifyAll(fnSms, fnEmail) {   
      setTimeout(function() {   
         console.log('starting notification process');   
         fnSms();   
         fnEmail();   
      }, 2000);   
   }   
   notifyAll(function() {   
      console.log("Sms send ..");   
   },  
   function() {   
      console.log("email send ..");   
   });   
   console.log("End of script"); //executes first or not blocked by others   
</script>

Следующий вывод отображается при успешном выполнении вышеуказанного кода.

End of script 
starting notification process 
Sms send .. 
Email send ..

В случае нескольких обратных вызовов код будет выглядеть устрашающе.

<script>   
   setTimeout(function() {   
      console.log("one");   
      setTimeout(function() {   
         console.log("two");   
         setTimeout(function() {   
            console.log("three");   
         }, 1000);   
      }, 1000);   
   }, 1000);   
</script>

ES6 приходит вам на помощь, вводя концепцию обещаний. Обещания - это «события продолжения», которые помогают выполнять несколько асинхронных операций вместе в гораздо более чистом стиле кода.

пример

Давайте разберемся в этом на примере. Ниже приведен синтаксис того же.

var promise = new Promise(function(resolve , reject) {    
   // do a thing, possibly async , then..  
   if(/*everthing turned out fine */)    resolve("stuff worked");  
   else     
   reject(Error("It broke"));  
});  
return promise;
// Give this to someone

Первым шагом к реализации обещаний является создание метода, который будет использовать обещание. Скажем, в этом примереgetSum()метод является асинхронным, т.е. его работа не должна блокировать выполнение других методов. Как только эта операция завершится, она позже уведомит вызывающего абонента.

В следующем примере (шаг 1) объект Promise объявляется var prom. Конструктор Promise сначала выполняет функции для успешного завершения работы, а другой - в случае возникновения ошибки.

Обещание возвращает результат вычисления, используя обратный вызов разрешения и передавая результат, то есть n1 + n2

Step 1 - разрешить (n1 + n2);

Если getSum () обнаруживает ошибку или непредвиденное состояние, он вызывает метод обратного вызова reject в Promise и передает информацию об ошибке вызывающей стороне.

Step 2 - отклонить (Ошибка («Негативы не поддерживаются»));

Реализация метода представлена ​​в следующем коде (ШАГ 1).

function getSum(n1, n2) {   
   varisAnyNegative = function() {   
      return n1 < 0 || n2 < 0;   
   }   
   var promise = new Promise(function(resolve, reject) {   
      if (isAnyNegative()) {   
         reject(Error("Negatives not supported"));   
      }   
      resolve(n1 + n2)
   });   
   return promise;   
}

На втором этапе подробно описывается реализация вызывающей стороны (ШАГ 2).

Вызывающий должен использовать метод then, который принимает два метода обратного вызова - первый для успеха и второй для неудачи. Каждый метод принимает один параметр, как показано в следующем коде.

getSum(5, 6)   
.then(function (result) {   
   console.log(result);   
},   
function (error) {   
   console.log(error);   
});

Следующий вывод отображается при успешном выполнении вышеуказанного кода.

11

Поскольку типом возвращаемого значения getSum () является Promise, у нас может быть несколько операторов then. Первое «then» будет иметь оператор возврата.

getSum(5, 6)   
.then(function(result) {   
   console.log(result);   
   returngetSum(10, 20); 
   // this returns another promise   
},   
function(error) {   
   console.log(error);   
})   
.then(function(result) {   
   console.log(result);   
}, 
function(error) {   
   console.log(error);
});

Следующий вывод отображается при успешном выполнении вышеуказанного кода.

11
30

В следующем примере выполняется три вызова then () с методом getSum ().

<script>   
   function getSum(n1, n2) {   
      varisAnyNegative = function() {   
         return n1 < 0 || n2 < 0;   
      }   
      var promise = new Promise(function(resolve, reject) {   
         if (isAnyNegative()) {   
            reject(Error("Negatives not supported"));   
         }   
         resolve(n1 + n2);   
      });   
      return promise;   
   }   
   getSum(5, 6)   
   .then(function(result) {   
      console.log(result);   
      returngetSum(10, 20); 
      //this returns another Promise   
   },   
   function(error) {   
      console.log(error);   
   })
   .then(function(result) {   
      console.log(result);   
      returngetSum(30, 40); 
      //this returns another Promise   
   }, 
   function(error) {   
      console.log(error);   
   })   
   .then(function(result) {   
      console.log(result);   
   }, 
   function(error) {         
      console.log(error);   
   });   
   console.log("End of script ");   
</script>

Следующий вывод отображается при успешном выполнении вышеуказанного кода.

Программа сначала отображает «конец сценария», а затем результаты одного за другим после вызова метода getSum ().

End of script  
11 
30 
70

Это показывает, что getSum () вызывается в асинхронном или неблокирующем стиле. Promise дает хороший и чистый способ работы с обратными вызовами.