2015-09-13 7 views
15

Ho letto $ q e prometto da giorni e mi sembra di capirlo ... un po '. Ho la seguente situazione nella pratica:

  1. Una richiesta $ http viene effettuata e controlla se è possibile effettuare una chiamata successiva.
  2. Se la prima chiamata fallisce, restituire "nessun dato", se ha esito positivo e dice che è possibile effettuare una chiamata, viene effettuata la seconda chiamata, in caso contrario - "nessun dato" di nuovo. Se la seconda chiamata ha esito positivo, restituisce i dati, in caso contrario - "nessun dato". Ecco come si presenta (circa, ho semplificato per idea generale, in modo da non preoccuparsi dei piccoli errori qui):

     return $http.get (something) 
          .then(function(allowedAccess){ 
           if(allowedAccess){ 
            return $http.get (somethingElse) 
             .then(function(result){return {data:result} }, 
             function(error){return {data:"n0pe"} } 
            ) 
           } else { 
            return {data:"n0pe"} 
           } 
          }, 
          function(){ return {data:"n0pe"} }); 
    

mi è stato detto di usare $ q qui. Non capisco davvero come o perché lo farei. Le chiamate $ http sono già promesse.

Se c'è un modo per rendere questo pulitore, non lo vedo. Ho appena finito di rileggere questo post on the subject. In sostanza, mi sto perdendo qualcosa/c'è un modo migliore per farlo?

Modifica: anche solo rileggere a tutorial on chaining promises - non gestisce affatto gli errori di chiamata. Fondamentalmente postando questo come due diligence.

Edit 2: Questo è più di un elaborato sulla teoria che sto chiedendo circa, estratto dal primo articolo:

Questo è un semplice esempio però. Diventa davvero potente se il tuo callback() restituisce un'altra promessa. In tal caso, il successivo() verrà eseguito solo una volta che la promessa si risolverà. Questo modello può essere utilizzato per le richieste HTTP seriali, per esempio (in cui una richiesta dipende dal risultato di una precedente):

Questo sembra parlare di catene come questo:

asyncFn1(1) 
    .then(function(data){return asyncFn2(data)}) 
    .then(function(data){return asyncFn3(data)}) 

Così , se capisco correttamente questo a). Non si applica a me perché non ho una terza funzione. b). Mi applicherebbe se avessi tre funzioni perché mentre eseguo un'istruzione if all'interno della prima richiesta $ http, e solo all'interno dell'istruzione if restituisco un'altra promessa. Quindi, in teoria, se avessi tre funzioni asincrone per la catena, avrei dovuto inserire la mia affermazione if in una promessa?

+0

http://stackoverflow.com/a/37175801/2518285 –

risposta

13

Le promesse aiutano davvero con la composizione del codice di effettuare chiamate asincrone.In altre parole, consentono di comporre il codice in modo simile a come si comporterà un insieme sincrono di chiamate (con l'uso di concatenato .then s) e come se il codice di sincronizzazione fosse in un blocco try/catch (con .catch).

Quindi, immaginare che le chiamate HTTP bloccavano - la logica avete apparirebbe in questo modo:

var allowedAccess, data; 
try { 
    allowedAccess = $http.get(something); 

    if (allowedAccess){ 
    try{ 
     var result = $http.get(somethingElse); 
     data = {data: result}; 
    } catch(){ 
     data = {data: "n0pe"}; 
    } 
    } else { 
    data = {data: "n0pe"}; 
    } 
} catch(){ 
    data = {data: "n0pe"}; 
} 
return data; 

Si potrebbe semplificare un po ':

var allowedAccess, result; 
try { 
    allowedAccess = $http.get(something); 
    var result; 
    if (allowedAccess) { 
    result = $http.get(somethingElse); 
    } else { 
    throw; 
    } 
    data = {data: result}; 
} catch() { 
    data = {data: "n0pe"}; 
} 
return data; 

E questo si tradurrebbe alla versione asincrona di:

return $http 
      .get(something) 
      .then(function(allowedAccess){ 
      if (allowedAccess){ 
       return $http.get(somethingElse); 
      } else { 
       return $q.reject(); // this is the "throw;" from above 
      } 
      }) 
      .then(function(result){ 
      return {data: result}; 
      }) 
      .catch(function(){ 
      return {data: "n0pe"}; 
      }) 

almeno, questo è il ragionamento si potrebbe applicare durante la composizione co de con rami e chiamate asincrone.

Non sto dicendo che la versione ho presentato è ottimale o meno - è è, tuttavia, più secca a causa di una sola gestione degli errori. Ma ti rendi conto che quando fai il numero .then(success, error) è equivalente a try/catch rispetto alla precedente operazione asincrona - questo potrebbe essere o meno necessario in base alla tua specifica circostanza.

+0

La ringrazio molto per la tua risposta dettagliata, che continua a elaborarla, tornerà ad accettare il tuo o il domani di Matt. – VSO

+0

Cosa stiamo rifiutando con $ q.reject() qui? Ho familiarità con l'uso di reject() su un rinvio creato con $ q.defer(). Qui è solo rifiutando il secondo $ http.call? Ma l'affermazione if non è una promessa un problema? Molto probabilmente mi manca qualcosa. – VSO

+0

@VSO, '$ q.reject' è equivalente a' throw' nel mondo di sincronizzazione. È una promessa respinta, quindi finirà nel file '.catch' piuttosto che nel prossimo' .then' –

-2

$ q contribuirà a ridurre piramide di chiamate in questo modo:

async-call1.then(... 
    aysnc-call2.then(... 

questo post del blog - http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/ - offre un modo pulito di fare più richieste HTTP. Notare l'approccio più pulito utilizzando $ q. Nel caso in cui si stesse colpendo un singolo endpoint HTTP, utilizzare il metodo sarebbe stato perfetto. Direi che anche quello che hai va bene; $ q potrebbe consentire una maggiore flessibilità in futuro.

Il post del blog descrive un servizio durante l'utilizzo di $ q e il codice sembra più pulito.

Sono un principiante con promesse anche, quindi prendi questo con un granello di sale.

+3

La domanda dell'OP richiede chiaramente chiamate sequenziali, poiché una seconda chiamata dipende dal parametro di ritorno del primo. '$ q.all' funziona quando le chiamate sono indipendenti l'una dall'altra –

+0

Punto buono, @NewDev. Grazie. – zedfoxus

7

Questo è come vorrei codificare questo tipo di problema:

// returns a promise that resolves some endpoint if allowed 
function getDataWithAccess(allowed){ 
    return allowed ? $http.get(someEndpoint) : $q.reject(); 
} 

// do something with data 
function handleData(data){ 
    // do stuff with your data 
} 

// main chain 
$http.get(accessCredEndpoint) 
    .then(getDataWithAccess) 
    .then(handleData) 
    .catch(function(err){ 
     return { data: "n0pe" }; 
    }); 

Sì, questo è molto simile la risposta di nuovo Dev, però ho voluto fare un punto di estrazione delle funzioni nelle proprie blocchi. Ciò rende il codice generale molto più leggibile.

+0

Grazie per la tua risposta, sembra che mi serva del tempo per digerirlo, tornerà ad accettare il tuo o Nuovo La risposta di Dev dopo un po 'di sonno. – VSO