ES6 - obietnice

Składnia obietnicy

Składnia związana z obietnicą jest wymieniona poniżej, gdzie, p jest przedmiotem obietnicy, resolve to funkcja, która powinna zostać wywołana, gdy obietnica zostanie pomyślnie wykonana i reject to funkcja, która powinna zostać wywołana, gdy obietnica napotka błąd.

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

Przykład

Poniższy przykład przedstawia funkcję add_positivenos_async()który dodaje dwie liczby asynchronicznie. Obietnica zostaje rozwiązana, jeśli przekazywane są wartości dodatnie. Obietnica jest odrzucana, jeśli przekazywane są wartości ujemne.

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

Wynik powyższego kodu będzie taki, jak wspomniano poniżej -

end
Handling success 30
Handling error NOT_Postive_Number_Passed

Obietnice łańcuchowe

Promises chaining może być używany, gdy mamy sekwencję asynchronous tasksdo wykonania jeden po drugim. Obietnice są powiązane, gdy obietnica zależy od wyniku innej obietnicy. Pokazuje to poniższy przykład

Przykład

W poniższym przykładzie add_positivenos_async() functiondodaje dwie liczby asynchronicznie i odrzuca, jeśli przekazywane są wartości ujemne. Wynik bieżącego wywołania funkcji asynchronicznej jest przekazywany jako parametr do kolejnych wywołań funkcji. Zwróć uwagę na każdythen() metoda zawiera instrukcję return.

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

Wynik powyższego kodu będzie taki, jak podano poniżej -

end
first result 30
second result 60
third result 120

Poniżej szczegółowo omówiono niektóre powszechnie używane metody obiektu obietnicy -

obietnica.all ()

Ta metoda może być przydatna do agregowania wyników wielu obietnic.

Składnia

Składnia promise.all() metoda jest wymieniona poniżej, gdzie, iterablejest obiektem iterowalnym. Np. Array.

Promise.all(iterable);

Przykład

Poniższy przykład wykonuje tablicę operacji asynchronicznych [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]. Kiedy wszystkie operacje zostaną zakończone, obietnica zostanie w pełni rozwiązana.

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

Wynik powyższego kodu będzie następujący -

end
30
70
110
all add operations done

promise.race ()

Ta funkcja przyjmuje tablicę obietnic i zwraca pierwszą rozliczoną obietnicę.

Składnia

Składnia promise.race()funkcja jest wymieniona poniżej, gdzie iterowalny jest iterowalnym obiektem. Np. Array.

Promise.race(iterable)

Przykład

Poniższy przykład przyjmuje tablicę [add_positivenos_async(10,20),add_positivenos_async(30,40)] operacji asynchronicznych.

Obietnica zostaje rozwiązana po zakończeniu dowolnej operacji dodawania. Obietnica nie będzie czekać na zakończenie innych operacji asynchronicznych.

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

Wynik powyższego kodu będzie następujący -

end
one of them is done
30

Promisesto czysty sposób implementacji programowania asynchronicznego w JavaScript (nowa funkcja ES6). Przed obietnicami wywołania zwrotne były używane do implementacji programowania asynchronicznego. Zacznijmy od zrozumienia, czym jest programowanie asynchroniczne i jego implementacji przy użyciu wywołań zwrotnych.

Zrozumienie oddzwaniania

Funkcja może być przekazana jako parametr do innej funkcji. Ten mechanizm jest określany jakoCallback. Callback byłby pomocny w wydarzeniach.

Poniższy przykład pomoże nam lepiej zrozumieć tę koncepcję.

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

w notifyAll()metoda pokazana powyżej, powiadomienie następuje poprzez wysłanie wiadomości SMS i wysłanie wiadomości e-mail. Dlatego wywołujący metodę notifyAll musi przekazać dwie funkcje jako parametry. Każda funkcja przejmuje jedną odpowiedzialność, taką jak wysyłanie SMS-ów i wysyłanie e-maili.

Poniższe dane wyjściowe są wyświetlane po pomyślnym wykonaniu powyższego kodu.

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

We wspomnianym powyżej kodzie wywołania funkcji są synchroniczne. Oznacza to, że wątek interfejsu użytkownika będzie czekał na zakończenie całego procesu powiadomienia. Połączenia synchroniczne stają się połączeniami blokującymi. Rozumiemy teraz połączenia nieblokujące lub asynchroniczne.

Zrozumienie AsyncCallback

Rozważ powyższy przykład.

Aby włączyć skrypt, wykonaj asynchroniczne lub nieblokujące wywołanie metody notifyAll (). Będziemy używaćsetTimeout()metoda JavaScript. Ta metoda jest domyślnie asynchroniczna.

Metoda setTimeout () przyjmuje dwa parametry -

  • Funkcja zwrotna.

  • Liczba sekund, po których zostanie wywołana metoda.

W tym przypadku proces powiadamiania został zakończony przekroczeniem limitu czasu. W związku z tym zajmie to dwie sekundy opóźnienia, ustawione przez kod. Zostanie wywołana funkcja notifyAll (), a główny wątek będzie kontynuowany, podobnie jak wykonywanie innych metod. W związku z tym proces powiadamiania nie blokuje głównego wątku 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>

Poniższe dane wyjściowe są wyświetlane po pomyślnym wykonaniu powyższego kodu.

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

W przypadku wielu wywołań zwrotnych kod będzie wyglądał przerażająco.

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

ES6 przychodzi ci na ratunek, wprowadzając pojęcie obietnic. Obietnice to „zdarzenia kontynuacji”, które pomagają w wykonywaniu wielu operacji asynchronicznych razem w znacznie bardziej przejrzystym stylu kodu.

Przykład

Zrozummy to na przykładzie. Poniżej znajduje się składnia tego samego.

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

Pierwszym krokiem do realizacji obietnic jest stworzenie metody, która będzie wykorzystywała obietnicę. Powiedzmy, że w tym przykładziegetSum()metoda jest asynchroniczna, tzn. jej działanie nie powinno blokować wykonywania innych metod. Zaraz po zakończeniu tej operacji, później powiadomi dzwoniącego.

Poniższy przykład (krok 1) deklaruje obiekt Promise „var promise”. Konstruktor obietnicy przejmuje funkcje najpierw w celu pomyślnego zakończenia pracy, a następnie w przypadku wystąpienia błędu.

Obietnica zwraca wynik obliczenia, używając funkcji zwrotnej rozstrzygnięcia i przekazując wynik, tj. N1 + n2

Step 1 - rozwiązać (n1 + n2);

Jeśli getSum () napotka błąd lub nieoczekiwany warunek, wywoła metodę wywołania zwrotnego odrzucenia w Promise i przekaże informacje o błędzie do wywołującego.

Step 2 - odrzucić (Błąd („Negatywy nie są obsługiwane”));

Implementacja metody jest podana w poniższym kodzie (KROK 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;   
}

Drugi krok przedstawia szczegóły implementacji dzwoniącego (KROK 2).

Wzywający powinien użyć metody „then”, która przyjmuje dwie metody wywołania zwrotnego - pierwszą dla sukcesu, a drugą dla niepowodzenia. Każda metoda przyjmuje jeden parametr, jak pokazano w poniższym kodzie.

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

Poniższe dane wyjściowe są wyświetlane po pomyślnym wykonaniu powyższego kodu.

11

Ponieważ typem zwracanym przez getSum () jest Obietnica, w rzeczywistości możemy mieć wiele instrukcji „then”. Pierwsze „wtedy” będzie miało instrukcję powrotu.

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

Poniższe dane wyjściowe są wyświetlane po pomyślnym wykonaniu powyższego kodu.

11
30

Poniższy przykład wywołuje trzy wywołania then () z metodą 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>

Poniższe dane wyjściowe są wyświetlane po pomyślnym wykonaniu powyższego kodu.

Program najpierw wyświetla „koniec skryptu”, a następnie wywołuje po kolei metodę getSum ().

End of script  
11 
30 
70

To pokazuje, że getSum () jest wywoływana w stylu asynchronicznym lub nieblokującym. Obietnica daje miły i czysty sposób radzenia sobie z Callbackami.