2016-06-28 21 views
11

Attualmente sto usando il servizio q $ da angolare per effettuare chiamate API come questo:

var deferred = $q.defer(); 
$http.get(config.apiHost + details.url) 
    .success(function (data) { 
     deferred.resolve(data); 
    }).error(function (msg) { 
     deferred.reject(msg); 
    }); 
return deferred.promise; 

ma possiamo anche usare questo metodo anche senza l'utilizzo di $ q:

return $http.get(config.apiHost + details.url) 
    .success(function (data) { 
     return data; 
    }).error(function (msg) { 
     return msg; 
    }); 

e da $ http si restituisce la promessa, mi può anche usare l'approccio più semplificato:

$http.get(config.apiHost + 'posts') 
     .success(function (data) { 
      console.log(data) 
     }).error(function (msg) { 
      console.log(msg); 
     }); 

Quindi qual è la differenza tra tutti questi specialmente tra $ q e $ http, in quanto entrambi i rendimenti promettono ed entrambi sono asincroni? Angular offre alcune funzionalità aggiuntive con $ q? Non riesco a trovare una buona risposta.

+0

È possibile restituire la promessa con altre operazioni asincrone con $ q. $ http restituisce una promessa dalle chiamate AJAX. – Hoyen

+0

altre operazioni come? –

+0

Come leggere i file o se è necessario utilizzare $ timeout – Hoyen

risposta

2

$q viene utilizzato principalmente per la compatibilità con le librerie che non supportano le promesse per impostazione predefinita e quando non è possibile fare affidamento su un'implementazione nativa di Promise (ad esempio nei browser più vecchi come IE9). Non c'è motivo (per te) di usarlo altrimenti. Un esempio sarebbe se si volesse creare uno $timeout basato sulla promessa. Lo stesso $http utilizza $q sotto il cofano per questi motivi esatti.

A differenza di ciò che gli altri (in quanto cancellati) le risposte hanno suggerito, si fa non necessario utilizzare $q al fine di "store" il risultato della $http promessa. Non consiglierei di conservare la promessa (poiché questo tende a portare il codice spaghetti), ma se dovete assolutamente farlo, potete semplicemente memorizzare la promessa risultante da $http; le promesse si eseguono solo una volta.

Qualsiasi funzione passata a then dopo che una promessa è stata risolta/respinta verrà risolta al prossimo tick, senza re-invocare l'azione originale che ha creato la promessa in primo luogo - IOW, il risultato della promessa è memorizzato all'interno di quell'oggetto.

Si noti inoltre che le promesse a catena, che è un po 'nervosa fuori portata per questa risposta, ma significa in sostanza che i seguenti pezzi di codice sono equivalenti

function legacyGet() { 
    const deferred = $q.defer() 
    $http.get('http://www.google.com') 
    .then((response) => deferred.resolve(Object.assign(response, {foo: bar})) 
    .catch((error) => deferred.reject(error)) 
    return deferred.defer 
} 

function modernGet() { 
    return $http.get('http://www.google.com') 
    .then((response) => Object.assign(response, {foo: bar})) 
} 

In sintesi: Il tuo titolo è sbagliato. Non preferiamo usare $ q, lo usiamo solo con parsimonia. Preferisci utilizzare una Promessa ES6 a meno che tu non abbia bisogno di supportare i browser che non ce l'hanno e non puoi usare un polyfill.

7

$http utilizza $q, il primo esempio è ridondante e lo stesso è il secondo. Hai solo bisogno di restituire la promessa che $http.get rendimenti:

return $http.get(config.apiHost + details.url); 

È possibile che questo è lo stesso come il primo pezzo di codice.

Inoltre, return msg non corrisponde a deferred.reject(msg). L'equivalente sarebbe throw msg o return $q.reject(msg)

Un'altra cosa da notare è che success e error sono non standard, si desidera utilizzare then e catch.

+0

Non direi che 'success' e' error' sono "non standard", appena deprecati: https://docs.angularjs.org/ api/ng/service/$ http – pulse0ne

+1

@ pulse0ne loro * sono * non standard se stai parlando della specifica di promessa A + –

+0

@DanPantry ah, sì, stavo erroneamente pensando che ti stavi riferendo al servizio angolare $ http. Per quanto riguarda le specifiche, non è standard e quasi certamente perché le persone angolari lo hanno deprecato. – pulse0ne

0

In gran parte angolare, tutti i servizi restituiscono solo promesse, ma vi sono alcuni casi in cui si desidera creare il proprio oggetto posticipato utilizzando $q.

Caso 1

Quando si utilizza una libreria che non supporta promessa o aver creato una propria funzione e si desidera tornare una promessa.

Caso 2

Quando si utilizza qualsiasi costrutto che di default restituisce una promessa, ma si desidera restituire una promessa separata sulla base di alcuni a una certa condizione.

Esempio: In angolari $http restituisce una promessa solo, ma ora se vuoi che se la risposta di questa promessa contiene un particolare valore, allora solo si desidera tornare risolto mancato ritorno altro allora avete bisogno di creare il proprio deffered object e è necessario risolvere o meno in base al valore restituito dalla risposta $http.

+0

Non hai bisogno di farlo. Promette catena. Puoi fare altrettanto facilmente '$ http.get(). Then (...)' e il valore restituito da 'then' sarà passato al successivo .then nella catena. Non è necessario utilizzare il proprio oggetto posticipato per questo. –

+0

Sto parlando della risposta del $ http ... come se volessi che la risposta contenga un certo valore piuttosto che risolvere la promessa o semplicemente rifiutare. –

+1

Questa risposta è imprecisa e sta descrivendo il comune anti-pattern differito – charlietfl