2016-02-25 20 views
16

La nuova funzione async/await TypeScript utilizza le promesse ES6. AngularJS utilizza le promesse del servizio $q con un'interfaccia leggermente diversa.

C'è un modo per utilizzare la funzionalità async/await di TypeScript con le promesse del servizio $q?

+1

Sì. Il primo problema è che devo convertire ogni promessa-risposta di ng-service per attenderlo contro di essa. Il secondo problema è che ES6-promesse generate dall'attesa dell'espressione non iniziano il ciclo di digest angolare – Random

risposta

16

Ecco come si fa:

angular.module('your app') 
     .run(['$window', '$q', function($window, $q) { 
      $window.Promise = $q; 
     }]); 
+0

Grazie, è molto più bello della mia versione. Non sapevo che il servizio $ q potesse essere utilizzato come costruttore compatibile con es6-promises – Random

+1

Questo funziona e lo sto utilizzando in diversi progetti ora. Ma non posso fare a meno di scuotere la sensazione che questo sia cattivo. Sostituire l'oggetto Promise globale con il servizio Angular $ q sembra ... hackish. –

+2

La sostituzione di Promise nativa con $ q è probabilmente la cosa peggiore che l'utente possa mai fare all'applicazione. Sono implementazioni fondamentalmente differenti che si comportano in modo diverso, questo rovinerà tutto il codice di terze parti che dipende da "Promise". L'affermazione sulla finestra $ 'hackish' è falsa - non è lì perché Angular non è in grado di usare la finestra nativa, ma perché DI è buono. – estus

3

Non penso che sarete in grado di usarli direttamente. Ma dovrebbe essere abbastanza facile da convertire q promessa in una promessa ++, qualcosa di simile:

function Convert<T>(qPromise): Promise<T> 
{ 
    return new Promise<T>((resolve, reject) => 
    { 
     qPromise.then((result: T) => resolve(result), (e) => reject(e)); 
    }); 
}; 
+4

Il problema è che in questo caso devo avvolgere ogni servizio ng che restituisce $ q promette. Inoltre, le promesse ES6 non iniziano il ciclo di digestione angolare. Quindi, in questo caso, devo chiamare '$ apply' dopo ogni' await' – Random

1

Infine ho usato la seguente soluzione:

declare var __awaiter: Function; 
(window as any).__awaiter = __awaiter; // set global __awaiter to avoid declaring default __awaiter in other files 
async() => { } // dummy async function to generate __awaiter code for current file 

angular.module('ts-awaiter', []).run(['$timeout', ($timeout: ng.ITimeoutService) => { 
    function wrap(func: Function) { 
     return function() { 
      func.apply(this, arguments); 
      $timeout(() => { }); // run angular digest 
     }; 
    } 

    var oldAwaiter = __awaiter; 
    (window as any).__awaiter = (thisArg: any, _arguments: any, P: Function, generator: any) => { 
     P = function (executor: Function) { 
      return new Promise<any>((resolve, reject) => { 
       resolve = wrap(resolve); 
       reject = wrap(reject); 
       executor(resolve, reject); 
      }); 
     }; 
     return oldAwaiter(thisArg, _arguments, P, generator); 
    }; 
}]); 

Comliper per tipografico 1.8 genera __awaiter funzione in tutti i file in cui L'operatore await viene utilizzato. Lo sostituisco con l'implementazione che passa il costruttore personalizzato Promise che avvia il ciclo di digest dopo ogni chiamata resolve e reject. Ecco esempio di utilizzo: https://github.com/llRandom/ts-awaiter

+0

Solo per curiosità come si gestisce questo rifiuto? blocco di cattura? – Luis

+0

Sì. Aggiunto un esempio al repository – Random

+0

Ciò potrebbe causare digerimenti non necessari e i digest sono il collo di bottiglia più comune per le prestazioni delle applicazioni AngularJS. E la soluzione non è applicabile al target ES2017 di TypeScript ... nativo async/await è già lì. – estus