繁体   English   中英

角$ q许诺和非线性链接

[英]Angular $q promises and non-linear chaining

大家好 我撞到了砖墙。 我正在尝试研究Angular异步方法调用,promise对象并实现针对特定问题的解决方案。 经过数小时的反复试验和代码重组,我可以确定答案就在我的鼻子底下,但我看不到它。

我有一种情况,必须使用$ http进行后端服务调用,这会产生一个承诺。 在promise的结果中,我将收到一个具有一个字符串属性和100个ID的数组的数据对象。 该后端服务一次仅提供100个ID的有效负载,因此,如该后端服务所提供的那样,我必须进行x个$ http调用才能到达列表的末尾。 根据我对诺言的理解,我必须在诺言的.then()方法中评估$ http响应,如果string属性为'N',那么我知道我必须再次调用后端服务以获得另一批100个ID。 传递完所有ID后,字符串将包含“ Y”,表示已发送完此字符,请勿再次调用。 对此计划无需评论,我知道它相当la脚,不幸的是我无法控制。 ;-)

如果需要更多异步调用,我研究的关于承诺的所有内容似乎都以线性方式说明了承诺链。 无论promise链是嵌套的还是扁平的,似乎我只能发出“已知”或固定数量的顺序调用,例如Promise1到Promise2,Promise3等。请原谅我在Promise方面的有限经验。

这是一个代码示例,您可以看到我卡在这里的位置,向下嵌套。 我不能仅仅希望3、5或10个电话后就“希望”我将获得所有ID。 我需要动态评估每个调用的结果,然后再次调用。

这是调用$ http的Angular服务

(function() {
'use strict';

  angular
      .module('myapp')
      .factory('IDservice', IDservice);

  function IDservice($http) {

    var service = {
    model: {
        error: {
          state: false,
          message: ''
        },
        ids: [],
        end: '',
      },
      GetIDs: function() {
        var request = 'some params...';
        var url = 'the url...';
        return $http.post(url, request).then(reqComplete).catch(reqFailed);

        function reqComplete(response) {
          service.model.ids = response.data.idList;
          service.model.end = response.data.end;
          return service.model;
        }

        function getIntradayMsrFailed(error) {
          service.model.error.state = true;
          service.model.error.message = error;
          return service.model;
        }

      }
    };
    return service;
  }

})();

这是调用Angular服务的Controller,它最终在相应的视图上驱动一些UI元素:

(function() {
  'use strict';

  angular
    .module('myapp')
    .controller('AvailableIDsController', AvailableIDsController);

  function AvailableIDsController($scope, $location, $timeout, IDservice) {
    var vm = this;
    vm.completeIDList = [];

    activate();    

    function activate() {
        IDservice.GetIDs().then(function(response){
          vm.completeIDList = response.ids;
          console.log('promise1 end');
            if(response.end === 'N'){
              IDservice.GetIDs().then(function(response){
                angular.forEach(response.ids,function(nextID){
                  vm.comleteIDList.push(nextID);
                 });
                console.log('promise2 end'); 
                if(response.end === 'N'){
                  IDservice.GetIDs().then(function(response){
                    angular.forEach(response.ids,function(nextID){
                      vm.comleteIDList.push(nextID);
                    });
                    console.log('promise3 end');
                  });   
                }
             });    
           }
        });         

     console.log('mainthread end');
     }
}
})();

您可以看到前进的方向……而且非常非常难看。

我需要一种在activate()方法内部的方法来调用一个方法,该方法将负责调用服务调用,并将结果返回到activate()中。 现在,仍然在activate()方法中,评估结果并确定是否再次调用,依此类推。一旦完成主处理线程,我就陷入了困境,在第一个承诺中就剩下了程序控制权。 从那里,您可以执行另一个承诺,等等,然后沿着兔子洞前进。 一旦进入这个陷阱,一切都会丢失。 显然,我没有这样做。 我错过了其他一些简单的难题。 任何建议将不胜感激!

您正在寻找普通的旧递归:

function AvailableIDsController($scope, $location, $timeout, IDservice) {
    var vm = this;
    vm.completeIDList = [];
    return activate(0);    

    function activate(i) {
        return IDservice.GetIDs().then(function(response) {
            [].push.apply(vm.completeIDList, response.ids); // simpler than the loop
            console.log('promise'+i+' end');
            if (response.end === 'N'){
                return activate(i+1);
            }
        });
     }
}

不要忘记return这样promise会链接在一起,您可以等待请求结束。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM