简体   繁体   English

角$ q许诺和非线性链接

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

Hello everyone out there. 大家好 I've hit a brick wall. 我撞到了砖墙。 I'm trying to research Angular async method calls, promise objects and implement a solution to a particular issue. 我正在尝试研究Angular异步方法调用,promise对象并实现针对特定问题的解决方案。 After a few hours of trial and error and restructuring my code, I'm certain at this point the answer is right under my nose but I cannot see it. 经过数小时的反复试验和代码重组,我可以确定答案就在我的鼻子底下,但我看不到它。

I have a scenario where I must use $http to make a backend service call, which yields a promise. 我有一种情况,必须使用$ http进行后端服务调用,这会产生一个承诺。 In the results of promise I will receive a data object with one string property and an array of 100 IDs. 在promise的结果中,我将收到一个具有一个字符串属性和100个ID的数组的数据对象。 This backend service will only deliver payloads of 100 IDs at a time, so I must make x number of $http calls to reach the end of the list, as provided by this backend service. 该后端服务一次仅提供100个ID的有效负载,因此,如该后端服务所提供的那样,我必须进行x个$ http调用才能到达列表的末尾。 As I understand promises, I must evaluate the $http response in the promise's .then() method and if the string property is 'N' then I know I must call the backend service again for another batch of 100 IDs. 根据我对诺言的理解,我必须在诺言的.then()方法中评估$ http响应,如果string属性为'N',那么我知道我必须再次调用后端服务以获得另一批100个ID。 After all IDs have been delivered the string will contain a 'Y' indicating that the end of this has been sent and don't call again. 传递完所有ID后,字符串将包含“ Y”,表示已发送完此字符,请勿再次调用。 No comment required on this scheme, I know it's fairly lame, and unfortunately out of my control. 对此计划无需评论,我知道它相当la脚,不幸的是我无法控制。 ;-) ;-)

Everything I've studied regarding promises just seem to illustrate chaining of promises, in a linear fashion, if more async calls are needed. 如果需要更多异步调用,我研究的关于承诺的所有内容似乎都以线性方式说明了承诺链。 Whether the promise chain is nested or flat, it seems like I can only make a "known" or fixed number of sequential calls, eg Promise1 to Promise2, to Promise3, etc. Forgive my limited experience with promises here. 无论promise链是嵌套的还是扁平的,似乎我只能发出“已知”或固定数量的顺序调用,例如Promise1到Promise2,Promise3等。请原谅我在Promise方面的有限经验。

Here is a code example, you can see where I'm stuck here, nesting downward. 这是一个代码示例,您可以看到我卡在这里的位置,向下嵌套。 I can't just "hope" after 3 or 5 or 10 calls I'll get all the IDs. 我不能仅仅希望3、5或10个电话后就“希望”我将获得所有ID。 I need to dynamically evaluate the result of each call and call again. 我需要动态评估每个调用的结果,然后再次调用。

Here is the Angular service which invokes $http 这是调用$ 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;
  }

})();

Here is the Controller which invokes the Angular service, which ultimately drives some UI elements on the respective view: 这是调用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');
     }
}
})();

You can see where that's going... and it's very, very ugly. 您可以看到前进的方向……而且非常非常难看。

I need a way, inside the activate() method, to call a method which will take care of invoking the service call and return the result back up to activate(). 我需要一种在activate()方法内部的方法来调用一个方法,该方法将负责调用服务调用,并将结果返回到activate()中。 Now, still in the activate() method, evaluate the result and determine whether to call again, etc. Where I'm stuck is once the main processing thread is done, you're left with program control in that first promise. 现在,仍然在activate()方法中,评估结果并确定是否再次调用,依此类推。一旦完成主处理线程,我就陷入了困境,在第一个承诺中就剩下了程序控制权。 From there, you can perform another promise, etc. and down the rabbit hole you go. 从那里,您可以执行另一个承诺,等等,然后沿着兔子洞前进。 Once I'm in this trap, all is lost. 一旦进入这个陷阱,一切都会丢失。 Clearly I'm not doing this right. 显然,我没有这样做。 I'm missing some other simple piece of the puzzle. 我错过了其他一些简单的难题。 Any suggestions would be so greatly appreciated! 任何建议将不胜感激!

You're looking for plain old recursion: 您正在寻找普通的旧递归:

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

Don't forget the return s so that the promises chain together and you can wait for the end of the requests. 不要忘记return这样promise会链接在一起,您可以等待请求结束。

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

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