【问题标题】:How to minimize the delays in collecting all promises in Angular JS如何最小化在 Angular JS 中收集所有 Promise 的延迟
【发布时间】:2015-03-13 15:41:35
【问题描述】:

请在下面查看我的代码。在“for”循环中,在每次迭代中,我都会进行 Ajax 调用并将 Promise 推送到数组中,并使用 $q.all 解决所有这些 Promise。但这会导致延迟,因为我需要等到在“for”循环中收集到所有承诺,然后在所有承诺都可用之后,我需要在 $q.all 中一一解决它们。

var promises = [];

for (var i = 0; i < dashboardslayoutArray.length; i++) {
    dashboardData.dashletteBeansList = [];
    dashboardData.dashletteBeansList[0] = dashboardslayoutArray[i];

    var dashlettePromise = DashboardsDataService.getTabDetails(dashboardData);
    promises.push(dashlettePromise);
}

$q.all(promises)
    .then(function(data) {
        // all promises were resolved here
    });

相反,我想做的是,尽快在'for'循环本身中解决promise,而不是将其推入'promises'以在$q.all中使用。比如,

for (var i = 0; i < dashboardslayoutArray.length; i++) {
    dashboardData.dashletteBeansList = [];
    dashboardData.dashletteBeansList[0] = dashboardslayoutArray[i];

    var dashlettePromise = DashboardsDataService.getTabDetails(dashboardData);

    dashlettePromise.then(function(data) {
        ...
    }, function(error) {
        alert(error);
    });
}    

但这并没有按预期工作。这里的第二个承诺结果会影响第一个承诺结果等。有什么解决方法吗?

根据@Benjamin Gruenbaum 的建议,我已将其更改为

angular.forEach(dashboardslayoutArray, function(dashboardslayout) {
    dashboardData.dashletteBeansList = [];
    dashboardData.dashletteBeansList[0] = dashboardslayout;

    var promise = DashboardsDataService.getTabDetails(dashboardData);

    promises.push(promise);

});

但是即使在这里,我怎样才能减少延迟呢?

@Benjamin Gruenbaum,我在下面总结我的问题:

var promises = [];
angular.forEach(dashboardslayoutArray, function(dashboardslayout) {
    dashboardData.dashletteBeansList = [];
    dashboardData.dashletteBeansList[0] = dashboardslayout;

    var promise = DashboardsDataService.getTabDetails(dashboardData);

    promises.push(promise);

});

$q.all(promises)
    .then(function(allData) {

        allData.forEach(function(data) {

            for (var dashVar = 0; dashVar < data.tabDetails.length; dashVar++) {
                var dashletteId = data.tabDetails[dashVar].dashletteId;
                var axisType = data.tabDetails[dashVar].axisType;
                // ...   draw c3 chart ...
            }
        });
    });

我需要进行多次 Ajax 调用,所以我使用了上述方法,效果很好。这里我所有的 Ajax 调用结果都是独立的,这些都不依赖于其他的。使用从每个 Ajax 调用返回的数据,我使用 Angularjs C3 指令绘制了一个图表。

但我面临的问题是延迟。要绘制四个 C3 图表,我需要使用 $q.all 进行四个 ajax 调用,只有在所有四个 Ajax 调用完成(已解决或被拒绝)后,我才能开始绘制 C3 图表。相反,我想做的是,一旦任何一个 Ajax 调用完成(已解决或被拒绝),我想根据该特定 Ajax 调用的结果开始绘制 C3 图表。所以我使用了以下方法来避免延迟所有承诺的排队。

angular.forEach(dashboardslayoutArray, function(dashboardslayout) {
    dashboardData.dashletteBeansList = [];
    dashboardData.dashletteBeansList[0] = dashboardslayout;

    var promise = DashboardsDataService.getTabDetails(dashboardData);

    promise.then(function(data) {

        for (var dashVar = 0; dashVar < data.tabDetails.length; dashVar++) {
            var dashletteId = data.tabDetails[dashVar].dashletteId;
            var axisType = data.tabDetails[dashVar].axisType;
            // ...   draw c3 chart ...
        }
    }, function(error) {
        alert(error);
    });

});

我的最后一个问题是,我在angular.forEach(dashboardslayoutArray , function(dashboardslayout) 中使用promise.then(function (data) 以避免延迟的方式是否正确?这种方法有什么潜在的问题吗?我希望,我已经清楚地表达了我的问题,如果没有,请告诉我,我会尽量做出 plunkr。

【问题讨论】:

  • 确保你在你的then处理程序中引用i——否则你最终会遇到臭名昭著的闭环问题,并且必须切换到@ 987654330@(或 angular.forEach)而不是 for 循环。
  • 我已将其更改为 angular.forEach(dashboardslayoutArray , function(dashboardslayout) { dashboardData.dashletteBeansList = []; dashboardData.dashletteBeansList[0] = dashboardslayout; var promise = DashboardsDataService.getTabDetails(dashboardData); promises.push(promise); });
  • 我不太明白 - 考虑制作一个孤立的 plunkr。
  • “我正在……用 $q.all 解决所有这些承诺”。不,你不是!为什么?因为$q.all() 不会导致承诺被解决——而是响应承诺被解决(或被拒绝)。让你记住这一点,问问自己这个问题是否有效。我相信不是。
  • 明白了@Roamer,谢谢。本杰明,要针对我的问题进行具体说明,需要提供大量编码,而且我认为可能没有必要浪费您的时间来处理与图表指令等相关的所有代码。所以我正在编辑我的问题并总结在末尾。如果可以帮助您清楚地了解我的要求,请告诉我。谢谢。

标签: angularjs promise angularjs-service angular-promise


【解决方案1】:

我的最后一个问题是,我在 angular.forEach(dashboardslayoutArray, function(dashboardslayout) 中使用 promise.then(function (data) 以避免延迟的方式是否正确?

是的,这正是你应该做的。 $q.all() 允许您在解决整套承诺后做某事。由于这与您想要做的相反,$q.all() 不是适合这里工作的工具。

您从未在第二个代码示例中向我们展示您在 then() 中的内容,但鉴于您说“第二个承诺结果影响第一个承诺结果等”,本杰明很可能Gruenbaum 的怀疑是正确的,并且是 i 循环变量导致了问题。切换到.forEach() 可以解决这个问题。

【讨论】:

  • 感谢 JLRshine,我接受了答案。将其更改为 .foreach 后,您就可以解决表达的问题。
猜你喜欢
  • 2019-07-26
  • 2023-03-05
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多