0

在角度代码中,我有一个这样的链式承诺:

// a function in LoaderService module.
var ensureTypesLoaded= function(){
   return loadContainerTypes($scope).then(loadSampleTypes($scope)).then(loadProjectList($scope)).then(loadSubjectTypes($scope));
 }

这些函数中的每一个都返回一个promise,它从资源中加载东西,并在错误和成功时额外修改$scope,例如:

         var loadProjectList = function ($scope) {

            // getAll calls inside a resource method and returns promise.
            return   ProjectService.getAll().then(
                function (items) {
                   // succesfull load
                    console.log("Promise 1 resolved");
                    $scope.projectList = items; 
                }, function () {
                    // Error happened
                    CommonService.setStatus($scope, 'Error!');
                });
        };

我打算在控制器初始化中的代码中使用,如下所示:

// Part of page's controller initialization code
LoaderService.ensureTypesLoaded($scope).then(function () {
            // do something to scope when successes
             console.log("I will do something here after all promises resolve");
            }, function () {
            // do something when error 
            });

但是,这并不像我想的那样工作。理想情况下,消息“在所有承诺解决后我会在这里做某事”必须在所有承诺解决后出现。相反,我可以看到它出现的时间早于来自列出 ensureTypesLoaded 的函数中已解决的承诺的消息。

我想创建一个函数 ensureTypesLoaded 这样,即:

  • 它返回一个承诺,当所有链式加载都被解决时,该承诺被解决;
  • 如果任何“内部”承诺失败,该函数不应继续下一次调用,而是返回被拒绝的承诺。
  • 显然,如果我调用 ensureTypesLoaded().then(...),则 then() 中的内容必须在 ensureTypesLoaded 中的所有内容都解决后调用。

请帮助我正确构建链式承诺。

4

1 回答 1

1

我认为问题出在您的 loadProjectList 函数中。因为 .then() 应该接收在结果时间调用的函数。通常是函数返回链承诺。

但是在您的情况下,您会立即并行调用所有负载。$scope 传递有点复杂。但我认为你的代码应该是这样的

//this fn is called immediatly on chain creation
var loadProjectList = function ($scope) {  
     //this fn is called when previous promise resolves
     return function(data) {
          //don't add error handling here
          ProjectService.getAll().then(...)
     }
}

这会导致您可能想要的串行加载。(请注意:以正确的方式并行执行 $q.all 使用)

最后,您应该只在 ensureTypesLoaded 中拥有错误处理程序,而不是在每个 Promise 中。

于 2014-07-30T08:56:26.127 回答