首页 文章

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

提问于
浏览
0

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

function1 - > function2 - > function3 - > function4

My Promise chain

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

但是我从来没有看到 .then 函数 .thenconsole.log


这是我的 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!');

2 回答

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

相关问题