2015-10-30 67 views
0

我想链在无极链4层的功能,像这样:为什么我的承诺链不能以这种嵌套的方式工作?

功能1 - >功能2 - >功能3 - > 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)函数,那么连锁我(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功能displayViewHeaderTags看到console.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!');

+0

对于你的'displayViewHeaderTags'功能,避免了[递延反模式](http://stackoverflow.com/q/23803743/1048572)和使用'$ q.all'代替 – Bergi

回答

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

?不遵守,我从buildUrlObject返回一个Promise,这就是它如何能够继续链。在'displayViewHeaderTags'中,我也以同样的方式返回一个Promise ...但是它不会在它的嵌套链中继续。在我的'ApiFactory'调用中没有错误,但我添加了catch。 –

+0

@LeonGaban - 学习Anid的代码,看看他们添加'return'语句的所有其他地方,以返回'.then()'处理程序中的promise。 – jfriend00

+0

使用'$ q.all'查看我的修改后的代码。你的if语句永远不会被击中,因为'i'在'length - 1'处加上了帽子。 –

2

你我是从来不一样的长度,因为我变从零开始(数组索引从零开始)。这意味着如果你有一个长度= 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); 
+0

AH!谢谢,那是我的问题......我现在看到我正在尝试捕获的日志,并且可以继续嵌套的Promise链。 –

相关问题