为什么我的Promise Chain不能以这种嵌套方式工作?

时间:2015-10-30 20:44:47

标签: javascript angularjs promise angular-promise

我想在Promise链中链接4个函数,如下所示:

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: enter image description here

^注意我从未见过这个日志:

viewHeader.vh.displayViewHeaderTags().then(function() {
    console.log('viewHeader.vh.displayViewHeaderTags FINISHED!');
});

理想情况下,我想将我的(3)函数放在其中,然后像我这样链接my(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的{​​{1}}函数中的.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; } 函数中,我点击了一个循环,该循环最多会运行3次,在完成数据后,它会填满,然后调用数组displayViewHeaderTags。然后返回deffered.resolve

那为什么我从来没有看到这个日志呢? return deferred.promise;

2 个答案:

答案 0 :(得分:2)

你的i永远不会与长度相同,因为i变量从零开始(数组索引从零开始)。这意味着如果你有一个长度为2的数组,你的i值将分别为0和1。它永远不会等于零。基本上,您希望条件为:

vm.viewTags.push(data.data.ticker_tag);
if (i + 1 === tags.length) {
    deferred.resolve();
}

无论如何,使用defer()code smell

更优雅的方法是使用$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 );

答案 1 :(得分:1)

你的连锁店并没有真正做任何事情,因为你没有从这些匿名功能中回复任何承诺。您可能没有看到该日志,因为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);
    });
}));