ES6 - Promesse

Promise Syntax

La sintassi relativa alla promessa è menzionata di seguito dove, p è l'oggetto della promessa, resolve è la funzione che dovrebbe essere chiamata quando la promessa viene eseguita correttamente e reject è la funzione che dovrebbe essere chiamata quando la promessa incontra un errore.

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

Esempio

L'esempio riportato di seguito mostra una funzione add_positivenos_async()che aggiunge due numeri in modo asincrono. La promessa viene risolta se vengono passati valori positivi. La promessa viene rifiutata se vengono passati valori negativi.

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

L'output del codice sopra sarà come indicato di seguito -

end
Handling success 30
Handling error NOT_Postive_Number_Passed

Promesse concatenate

Promises chaining può essere utilizzato quando abbiamo una sequenza di asynchronous tasksda fare uno dopo l'altro. Le promesse sono concatenate quando una promessa dipende dal risultato di un'altra promessa. Questo è mostrato nell'esempio sotto

Esempio

Nell'esempio seguente, add_positivenos_async() functionaggiunge due numeri in modo asincrono e rifiuta se vengono passati valori negativi. Il risultato della chiamata di funzione asincrona corrente viene passato come parametro alle successive chiamate di funzione. Nota ciascunothen() metodo ha una dichiarazione di ritorno.

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

L'output del codice precedente sarà come indicato di seguito:

end
first result 30
second result 60
third result 120

Alcuni metodi comuni utilizzati dell'oggetto promessa sono discussi di seguito in dettaglio:

promise.all ()

Questo metodo può essere utile per aggregare i risultati di più promesse.

Sintassi

La sintassi per il promise.all() metodo è menzionato di seguito, dove, iterableè un oggetto iterabile. Ad esempio, Array.

Promise.all(iterable);

Esempio

L'esempio fornito di seguito esegue un array di operazioni asincrone [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]. Quando tutte le operazioni sono state completate, la promessa è completamente risolta.

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

L'output del codice precedente sarà il seguente:

end
30
70
110
all add operations done

promise.race ()

Questa funzione accetta una serie di promesse e restituisce la prima promessa che è stata saldata.

Sintassi

La sintassi per il promise.race()la funzione è menzionata di seguito, dove iterable è un oggetto iterabile. Ad esempio, Array.

Promise.race(iterable)

Esempio

L'esempio fornito di seguito accetta un array [add_positivenos_async(10,20),add_positivenos_async(30,40)] di operazioni asincrone.

La promessa viene risolta ogni volta che viene completata una qualsiasi delle operazioni di aggiunta. La promessa non attenderà il completamento di altre operazioni asincrone.

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

L'output del codice precedente sarà il seguente:

end
one of them is done
30

Promisessono un modo pulito per implementare la programmazione asincrona in JavaScript (nuova funzionalità ES6). Prima delle promesse, venivano utilizzati i callback per implementare la programmazione asincrona. Cominciamo col capire che cos'è la programmazione asincrona e la sua implementazione, usando i callback.

Capire la richiamata

Una funzione può essere passata come parametro a un'altra funzione. Questo meccanismo è definito come aCallback. Una richiamata sarebbe utile negli eventi.

Il seguente esempio ci aiuterà a comprendere meglio questo concetto.

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

Nel notifyAll()metodo mostrato sopra, la notifica avviene tramite l'invio di SMS e l'invio di una e-mail. Quindi, il richiamo del metodo notifyAll deve passare due funzioni come parametri. Ogni funzione assume un'unica responsabilità come l'invio di SMS e l'invio di una e-mail.

Il seguente output viene visualizzato in caso di corretta esecuzione del codice precedente.

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

Nel codice sopra menzionato, le chiamate di funzione sono sincrone. Significa che il thread dell'interfaccia utente sarebbe in attesa di completare l'intero processo di notifica. Le chiamate sincrone diventano chiamate di blocco. Comprendiamo ora le chiamate non bloccanti o asincrone.

Capire AsyncCallback

Considera l'esempio sopra.

Per abilitare lo script, eseguire una chiamata asincrona o non bloccante al metodo notifyAll (). Useremo ilsetTimeout()metodo di JavaScript. Questo metodo è asincrono per impostazione predefinita.

Il metodo setTimeout () accetta due parametri:

  • Una funzione di callback.

  • Il numero di secondi dopo i quali verrà chiamato il metodo.

In questo caso, il processo di notifica è stato terminato con timeout. Quindi, ci vorrà un ritardo di due secondi, impostato dal codice. Verrà richiamato notifyAll () e il thread principale procede come se eseguisse altri metodi. Pertanto, il processo di notifica non bloccherà il thread JavaScript principale.

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

Il seguente output viene visualizzato in caso di corretta esecuzione del codice precedente.

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

In caso di più callback, il codice sembrerà spaventoso.

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

ES6 viene in tuo soccorso introducendo il concetto di promesse. Le promesse sono "eventi di continuazione" e ti aiutano a eseguire più operazioni asincrone insieme in uno stile di codice molto più pulito.

Esempio

Capiamolo con un esempio. Di seguito è riportata la sintassi per lo stesso.

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

Il primo passo verso l'attuazione delle promesse è creare un metodo che utilizzerà la promessa. Diciamo in questo esempio, ilgetSum()metodo è asincrono, ovvero il suo funzionamento non dovrebbe bloccare l'esecuzione di altri metodi. Non appena questa operazione sarà completata, verrà successivamente notificato al chiamante.

Il seguente esempio (passaggio 1) dichiara un oggetto Promise "var promise". Il Promise Constructor passa alle funzioni prima per il completamento con successo del lavoro e un altro in caso di errore.

La promessa restituisce il risultato del calcolo utilizzando il callback di risoluzione e passando il risultato, ovvero n1 + n2

Step 1 - risolvere (n1 + n2);

Se getSum () incontra un errore o una condizione imprevista, richiamerà il metodo di callback di rifiuto in Promise e passerà le informazioni sull'errore al chiamante.

Step 2 - rifiuta (Errore ("Negativi non supportati"));

L'implementazione del metodo è fornita nel codice seguente (PASSAGGIO 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;   
}

Il secondo passaggio descrive in dettaglio l'implementazione del chiamante (PASSAGGIO 2).

Il chiamante dovrebbe utilizzare il metodo "then", che accetta due metodi di callback: il primo per il successo e il secondo per il fallimento. Ogni metodo accetta un parametro, come illustrato nel codice seguente.

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

Il seguente output viene visualizzato in caso di corretta esecuzione del codice precedente.

11

Poiché il tipo di ritorno di getSum () è una promessa, possiamo effettivamente avere più istruzioni "then". Il primo "then" avrà una dichiarazione di ritorno.

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

Il seguente output viene visualizzato in caso di corretta esecuzione del codice precedente.

11
30

L'esempio seguente emette tre chiamate then () con il metodo 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>

Il seguente output viene visualizzato in caso di corretta esecuzione del codice precedente.

Il programma visualizza prima 'end of script' e poi i risultati della chiamata al metodo getSum (), uno per uno.

End of script  
11 
30 
70

Questo mostra che getSum () è chiamato in stile asincrono o non bloccante. Promise offre un modo carino e pulito per gestire i Callback.