Aspetta che tutte le promesse si risolvano

Quindi ho una situazione in cui ho più catene di promise di lunghezza sconosciuta. Voglio che un’azione venga eseguita quando tutte le CATENE sono state elaborate. È ansible? Ecco un esempio:

app.controller('MainCtrl', function($scope, $q, $timeout) { var one = $q.defer(); var two = $q.defer(); var three = $q.defer(); var all = $q.all([one.promise, two.promise, three.promise]); all.then(allSuccess); function success(data) { console.log(data); return data + "Chained"; } function allSuccess(){ console.log("ALL PROMISES RESOLVED") } one.promise.then(success).then(success); two.promise.then(success); three.promise.then(success).then(success).then(success); $timeout(function () { one.resolve("one done"); }, Math.random() * 1000); $timeout(function () { two.resolve("two done"); }, Math.random() * 1000); $timeout(function () { three.resolve("three done"); }, Math.random() * 1000); }); 

In questo esempio, ho impostato un $q.all() per le promesse uno, due e tre che verranno risolti in un momento casuale. Poi aggiungo promesse alle estremità di uno e tre. Voglio che all risolva quando tutte le catene sono state risolte. Ecco l’output quando eseguo questo codice:

 one done one doneChained two done three done ALL PROMISES RESOLVED three doneChained three doneChainedChained 

C’è un modo per aspettare che le catene si risolvano?

Voglio che tutto si risolva quando tutte le catene sono state risolte.

Certo, allora passa la promise di ogni catena al all() invece delle promesse iniziali:

 $q.all([one.promise, two.promise, three.promise]).then(function() { console.log("ALL INITIAL PROMISES RESOLVED"); }); var onechain = one.promise.then(success).then(success), twochain = two.promise.then(success), threechain = three.promise.then(success).then(success).then(success); $q.all([onechain, twochain, threechain]).then(function() { console.log("ALL PROMISES RESOLVED"); }); 

La risposta accettata è corretta. Vorrei fornire un esempio per elaborarlo un po ‘a quelli che non hanno familiarità con la promise .

Esempio:

Nel mio esempio, ho bisogno di sostituire gli attributi src dei tag img con diversi URL mirror, se disponibili, prima di rendere il contenuto.

 var img_tags = content.querySelectorAll('img'); function checkMirrorAvailability(url) { // blah blah return promise; } function changeSrc(success, y, response) { if (success === true) { img_tags[y].setAttribute('src', response.mirror_url); } else { console.log('No mirrors for: ' + img_tags[y].getAttribute('src')); } } var promise_array = []; for (var y = 0; y < img_tags.length; y++) { var img_src = img_tags[y].getAttribute('src'); promise_array.push( checkMirrorAvailability(img_src) .then( // a callback function only accept ONE argument. // Here, we use `.bind` to pass additional arguments to the // callback function (changeSrc). // successCallback changeSrc.bind(null, true, y), // errorCallback changeSrc.bind(null, false, y) ) ); } $q.all(promise_array) .then( function() { console.log('all promises have returned with either success or failure!'); render(content); } // We don't need an errorCallback function here, because above we handled // all errors. ); 

Spiegazione:

Da documenti AngularJS:

Il metodo then :

quindi (successCallback, errorCallback, notifyCallback) - indipendentemente dal momento in cui la promise è stata o verrà risolta o rifiutata, chiama uno dei callback di successo o di errore in modo asincrono non appena il risultato è disponibile. I callback vengono chiamati con un singolo argomento : il motivo del risultato o del rifiuto.

$ Q.all (promesse)

Combina più promesse in una singola promise che viene risolta quando tutte le promesse di input vengono risolte.

Il promises param può essere una serie di promesse.

Informazioni su bind() , Ulteriori informazioni qui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Recentemente ha avuto questo problema ma con un numero imprecisato di promesse. Risolto usando jQuery.map () .

 function methodThatChainsPromises(args) { //var args = [ // 'myArg1', // 'myArg2', // 'myArg3', //]; var deferred = $q.defer(); var chain = args.map(methodThatTakeArgAndReturnsPromise); $q.all(chain) .then(function () { $log.debug('All promises have been resolved.'); deferred.resolve(); }) .catch(function () { $log.debug('One or more promises failed.'); deferred.reject(); }); return deferred.promise; } 

È ansible utilizzare “attendere” in una “funzione asincrona” .

 app.controller('MainCtrl', async function($scope, $q, $timeout) { ... var all = await $q.all([one.promise, two.promise, three.promise]); ... } 

NOTA: non sono sicuro al 100% che si possa chiamare una funzione asincrona da una funzione non asincrona e ottenere i risultati corretti.

Detto questo, questo non sarebbe mai stato utilizzato su un sito web. Ma per test di carico / test di integrazione … forse.

Codice di esempio:

 async function waitForIt(printMe) { console.log(printMe); console.log("..."+await req()); console.log("Legendary!") } function req() { var promise = new Promise(resolve => { setTimeout(() => { resolve("DARY!"); }, 2000); }); return promise; } waitForIt("Legen-Wait For It");