Я хочу связать 4 функции в цепочке Promise следующим образом:
function1 → function2 → function3 → function4
Моя цепочка обещаний
if ($location.$$url !== "/dashboard") {
vm.customURL = true;
// (1) Set root vars & Rebuild tickerTagsContainer:
var promise = TagFactory.buildUrlObject($location.$$url).then(function() {
console.log('TagFactory.buildUrlObject PROMISE returned');
}).then(function() {
console.log('(2) Re-display tags in viewHeader');
// (2) Re-display tags in viewHeader:
viewHeader = ScopeFactory.getScope('viewHeader');
viewHeader.vh.displayViewHeaderTags().then(function() {
console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
});
}).then(function() {
// (3) Reselect timeSpan:
console.log('(3) Reselect timeSpan');
viewHeader.vh.toggleTimeSpan(vm.timeSpan);
// (4) Refresh URL:
console.log('(4) Refresh URL');
ViewFactory.remakeViewObject($location.$$url);
});
}
В результате console.logs:
^ Примечание. Я никогда не вижу этот журнал:
viewHeader.vh.displayViewHeaderTags().then(function() {
console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
});
В идеале я хочу разместить в нем свою (3) функцию, а затем привязать ее (4) так:
viewHeader.vh.displayViewHeaderTags().then(function() {
console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
console.log('(3) Reselect timeSpan');
viewHeader.vh.toggleTimeSpan(vm.timeSpan).then(function() {
console.log('(4) Refresh URL');
ViewFactory.remakeViewObject($location.$$url);
});
});
Однако я никогда не вижу console.log
из функции .then
для displayViewHeaderTags
Вот как выглядит мой displayViewHeaderTags
:
function displayViewHeaderTags() {
vm.viewTickerTags = [];
vm.viewTickerTags = TagFactory.retrieveTickerTags('all');
var deferred = $q.defer();
var tikObjs = vm.viewTickerTags.map(function(el) { return el.ticker; });
var tagObjs = vm.viewTickerTags.map(function(el) { return el.tags; });
var tags = _.flatten(tagObjs);
// forEach loops up to 3 times:
tags.forEach(function(tag, i) {
vm.viewTags = [];
ApiFactory.getTagDataSilm(tag.term_id).then(function(data) {
vm.viewTags.push(data.data.ticker_tag);
if (i === tags.length) {
deferred.resolve();
}
});
});
return deferred.promise;
}
Внутри моей функции displayViewHeaderTags
я нажимаю цикл, который будет работать до 3-х раз, после того, как он будет получать данные, он заполнит и массив затем deffered.resolve
. затем возвращает его return deferred.promise;
Так почему я никогда не вижу этот журнал? console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
Ваша цепочка ничего не делает, так как вы не возвращаете обещание от любой из этих анонимных функций. Вы не видите этот журнал, вероятно, потому, что ApiFactory.getTagDataSilm
не работает или никогда не разрешает. Попробуйте добавить обработчик ошибок в поток.
if ($location.$$url !== "/dashboard") {
vm.customURL = true;
// (1) Set root vars & Rebuild tickerTagsContainer:
var promise = TagFactory.buildUrlObject($location.$$url).then(function() {
console.log('TagFactory.buildUrlObject PROMISE returned');
}).then(function() {
console.log('(2) Re-display tags in viewHeader');
// (2) Re-display tags in viewHeader:
viewHeader = ScopeFactory.getScope('viewHeader');
return viewHeader.vh.displayViewHeaderTags().then(function() {
console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
});
}).then(function() {
// (3) Reselect timeSpan:
console.log('(3) Reselect timeSpan');
return viewHeader.vh.toggleTimeSpan(vm.timeSpan);
}).then(function() {
// (4) Refresh URL:
console.log('(4) Refresh URL');
return ViewFactory.remakeViewObject($location.$$url);
}).catch(function(error) {
console.log('Something failed', error);
});
}
В displayViewHeaderTags
вы можете использовать $q.all
, так что отклонения обрабатываются для вас:
// forEach loops up to 3 times:
vm.viewTags = [];
return $q.all(_.map(tags, function(tag) {
return ApiFactory.getTagDataSilm(tag.term_id).then(function(data) {
vm.viewTags.push(data.data.ticker_tag);
});
}));
displayViewHeaderTags
я также возвращаю Promise таким же образом ... однако он не продолжается в своей вложенной цепочке. В моем вызове ApiFactory
нет ошибки, но я добавил улов.
return
заявления для возврата обещаний внутри .then()
обработчиков.
Ваш я никогда не совпадает с длиной, поскольку переменная я начинается с нуля (индексы массива начинаются с нуля). Это означает, что если у вас есть массив с длиной = 2, ваши значения я будут равны 0 и 1 соответственно. Он никогда не будет равен нулю. В принципе, вам нужно условие:
vm.viewTags.push(data.data.ticker_tag);
if (i + 1 === tags.length) {
deferred.resolve();
}
Во всяком случае, использование defer()
является запахом кода.
Более элегантный способ сделать это будет использовать $ q.all
var allPromises = [];
var promise;
tags.forEach(function(tag) {
vm.viewTags = [];
promise = ApiFactory.getTagDataSilm(tag.term_id).then(function(data) {
vm.viewTags.push(data.data.ticker_tag);
});
// Create an array of promises, one promise for each request
allPromises.push( promise );
});
// Return a new promise that will only be resolved
// when all the promises of the array 'allPromises' are resolved,
// or is rejected when one of them is.
return $q.all( allPromises );
displayViewHeaderTags
избегайте отложенного антипаттерна и используйте вместо него$q.all