Ждите всех обещаний решить

Поэтому у меня есть ситуация, когда у меня есть несколько цепочек обещаний неизвестной длины. Я хочу, чтобы некоторые действия выполнялись, когда все ЦЕЛИ были обработаны. Возможно ли это? Вот пример:

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); }); 

В этом примере я установил $q.all() для обещаний один, два и три, которые будут решены в какое-то случайное время. Затем я добавляю обещания на концах одного и трех. Я хочу, чтобы все решалось, когда все цепи были разрешены. Вот результат, когда я запускаю этот код:

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

Есть ли способ дождаться, когда цепи будут решены?

Я хочу, чтобы все решалось, когда все цепи были разрешены.

Конечно, тогда просто передайте promise каждой цепочки во all() вместо первоначальных обещаний:

 $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"); }); 

Принятый ответ правильный. Я хотел бы привести пример, чтобы немного разобраться с теми, кто не знаком с promise .

Пример:

В моем примере мне нужно заменить атрибуты src тегов img разными зеркальными URL-адресами, если они доступны до рендеринга содержимого.

 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. ); 

Объяснение:

Из документов AngularJS:

then метод:

затем (successCallback, errorCallback, notifyCallback) - независимо от того, когда promise было или будет разрешено или отклонено, затем вызывает один из успешных или обратных вызовов асинхронно, как только результат будет доступен. Обратные вызовы вызываются с помощью одного аргумента : причина или отклонение.

$ Q.all (обещания)

Объединяет несколько обещаний в единое promise, которое разрешается, когда все вступительные обещания разрешаются.

Параметр promises может быть множеством обещаний.

О bind() , Дополнительная информация здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Недавно возникла эта проблема, но с неподтвержденным количеством обещаний. Решено использовать 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; } 

Есть выход. $q.all(...

Вы можете проверить следующие вещи:

http://jsfiddle.net/ThomasBurleson/QqKuk/

http://denisonluz.com/blog/index.php/2013/10/06/angularjs-returning-multiple-promises-at-once-with-q-all/

Вы можете использовать «ожидание» в «асинхронной функции» .

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

ПРИМЕЧАНИЕ. Я не уверен на 100%, что вы можете вызвать функцию async из функции non-async и получить правильные результаты.

Тем не менее, это никогда не будет использоваться на веб-сайте. Но для тестирования нагрузки / интеграции … может быть.

Пример кода:

 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"); 
  • AngularJs - получить список всех зарегистрированных модhive
  • получение ng-объекта, выбранного с помощью ng-change
  • Использование фильтра даты и времени в формате AngularJS с датой UTC
  • Альтернатива ng-show / -hide или как загрузить только соответствующий раздел DOM
  • Фильтрация углового 1.2 ng-repeat с помощью «track by» с помощью булевого свойства
  • Как передать некоторые данные от одного controllerа другому controllerу-сверстнику
  • AngularJS - функция перехода к директиве
  • Как обновить метаtags в AngularJS?
  • AngularJS intellisense не работает на Visual Studio 2015
  • Как кэшировать сервис http get в angularjs
  • Заменить узел ng-include шаблоном?
  • Давайте будем гением компьютера.