2014-12-10 16 views
11

Sto imparando AngularJS dopo la conversione da jQuery per alcuni anni. E alcuni bit sono molto più intuitivi. Alcuni non così tanto :).

Sto cercando di capire come utilizzare le promesse, in particolare $ q in uso con $ http e non sembrano esserci troppe informazioni attorno a queste due combinate che riesco a trovare.

Perché dovrei usare le promesse al posto del callback di successo/errore? Entrambi fanno l'uso di callback in realtà, quindi perché una promessa è considerata migliore? Per esempio. Potrei impostare una funzione get(...) come segue:

function get(url, success, error) { 
    success = success || function() {}; 
    error = error || function() {}; 

    $http.get(url) 
     .success(function (data) { 
      success(data); 
     }) 
     .error(function (error) { 
      error(error); 
     }); 
} 

get('http://myservice.com/JSON/', 
    function() { 
     // do something with data 
    }, 
    function() { 
     // display an error 
    } 
); 

Il che è un bene perché mi dà il controllo completo su ciò che sta accadendo (?). Se chiamo get(...) allora posso controllare qualsiasi successo/errore ovunque venga chiamato get.

Se converto questa opzione per utilizzare le promesse, allora ottengo:

function get(url) { 
    return $http.get(url) 
     .then(function (data) { 
      return data; 
     }, 
     function (error) { 
      return error; 
     }); 
} 

get('http://myservice.com/JSON/') 
    .then(function (data) { 
     // do something with data 
    }); 
    // cannot handle my errors? 

Che è condensato, sono d'accordo; inoltre, non dobbiamo preoccuparci esplicitamente della funzione di richiamo/errore, ma sembra che abbia perso il controllo sulla mia chiamata di errore per l'avvio - perché non riesco a configurare un secondo callback per gestire un errore.

Ciò significa che se utilizzo questa funzione in un servizio che può essere utilizzato da più controller, non è possibile aggiornare l'IU per avvisare l'utente di un errore.

Mi manca qualcosa? C'è una ragione per cui le promesse sono preferite? Non riesco a trovare un esempio perché.

+1

Prima di tutto la notazione completa per 'then' è' then (successCallback, errorcallback) '. Quindi puoi ancora gestire gli errori. Quindi, puoi anche usare metodi separati come ".success" e "fail". – dfsq

+2

è possibile concatenare promesse, è il più grande vantaggio per me – harishr

+0

@dfsq Oh OK - I am my callback di errore non è stato attivato quando ho usato 'then' per chiamare' http: // myservice.com/JSON/'. Dovrò riprovare. Does.then (successCallback, errorCallback) fa lo stesso di .success (successCallback) .fail (errorCallback)? – keldar

risposta

23

In genere si gestiscono i task asincroni in Javascript con i callback;

$.get('path/to/data', function(data) { 
    console.log(data); 
}); 

Funziona bene, ma inizia a complicare quando si entra in quello che viene chiamato "l'inferno del callback";

$.get('path/to/data', function(data) { 
    $.get('path/to/data2' + data, function(data2) { 
    $.get('path/to/data3' + data2, function(data3) { 
     manipulate(data, data2, data3); 
    }, errorCb); 
    }, errorCb); 
}, errorCb); 

L'alternativa sta funzionando con promesse e oggetto posticipato;

Deferreds - representing units of work 
Promises - representing data from those Deferreds 

Attaccando a questo ordine del giorno possono aiutare a voi in tutti i casi AsyncTask estremo:

  1. di una chiamata normale che hanno bisogno di ottenere i dati dal server, manipolarla, e ritornare al campo di applicazione
  2. Si dispone di più chiamate che ciascuno è a seconda del prezioso (strategia cahin)
  3. Si desidera inviare multipla (parallelo) chiama e gestire il loro successo in 1 blocco
  4. volete il codice da orginized (impedire che fare con i risultati di gestione sui controller)

Il vostro compito è il più facile da maneggiare con $ q e $ http

function get(url) { 
    var deferred = $q.defer(); 
    $http.get(url) 
     .success(function (data) { 
      deferred.resolve(data); 
     }) 
     .error(function (error) { 
      deferred.reject(error); 
     }); 

    return deferred.promise; 
} 

e chiamare la funzione di servizio è la stessa

get('http://myservice.com/JSON/') 
.then(function (data) { 
    // do something with data 
}); 
// cannot handle my errors? 
+0

Questo è fantastico - grazie! Qual è la differenza tra la mia frase 'get (...)' e la tua? Rendo il risultato '$ http.get() dove si usa esplicitamente' $ q.defer() '. Il mio è sbagliato? – keldar

+1

L'oggetto deffer è un wrapper di chiamate, quindi non sto restituendo la promessa creata dalla chiamata $ http Sto restituendo le promesse di wrapping (sarebbe lo stesso se fai call più chiamate) e proprio quando tutto è risolto " allora "la funzione di quella promessa viene lanciata. E no - non c'è giusto o sbagliato, anche tu funzionerebbe, ma non è la migliore linea guida @keldar –

+0

l'unico modo in cui posso ottenere il mio callback_chained_ error è che se lancio un errore nel mio primo? – keldar

1

è possibile gestire l'errore come questo:

get('http://myservice.com/JSON/') 
    .then(function (data) { 
     // do something with data 
    }, 
    function (error) { 
     //do something with error 
    }); 

Ma purtroppo dal momento che avete già catturato l'errore quindi l'errore finale non verrà attivato. Avrai anche lo stesso problema con il successo.

Per farlo funzionare, è necessario utilizzare $ q.

function get(url) { 
    var deferred = $q.defer(); 

    $http.get(url) 
     .success(function (data) { 
      deferred.resolve(data); 
     }) 
     .error(function (error) { 
      deferred.reject(error); 
     }); 

    return deferred.promise; 
} 

Inoltre, non è necessario passare le funzioni di errore e di successo perché è possibile utilizzare invece le promesse.

+1

È necessario anche "gettare" un errore sulla funzione get per farlo funzionare, poiché "return error" non farà il lavoro. –

+0

Questo potrebbe spiegare il motivo per cui non funzionava per me: presumo che si verifichino errori diversi nella richiamata dell'errore e che gli incatenati riceveranno gli errori nelle loro richiamate? – keldar