2016-07-07 93 views
0

我已经失去了多少次尝试完成此项工作的计数。我只是不明白。角度调用循环中的函数/函数按特定顺序

让我们假设我有以下API调用:

API /客户(卡斯特)

API /订单(订单ID)

API /产品(产品ID)

API /相关(relatedid)

当所有说,做,我需要包含所有的数据作为阵列和子阵列(将在下面解释)的单个对象。

我需要从api/customer进行api调用。退货将作为客户的先前订单作为对象数组。我们假装他们做了三个命令。

每个对象内是各种键:值对,其中包括一个所谓的“产品”其本身是的productid数字阵列。

现在,我必须遍历所有的产品ID号,并与每个人,请拨打:

API /产品(产品ID)

这也将返回的必经之地循环找到每个产品的一个数组“relatedid”的价值。

接着上面的循环中我必须再次联系与API:

API /相关(relatedid)

,然后返回在每一个客户的每一个订单涉及到每个产品的产品。

当所有是说,做一个客户可能有三个订单,每个订单可能有5种产品,每种产品可能有10种相关产品。

你如何编写这样的事情,确保从上到下每个API调用继续之前完成?你如何在多个循环中做到这一点?

当一切都说过和做过我希望这样的事情:

{ 
customerid: 10 
previousOrderids: {10, 11, 12} 
orderedProducts: {10: {101, 102, 103, 104}, 11:{201, 202, 203, 204}, 12:{301, 302} 
relatedProducts: {101: {5, 6, 7}, 102: {7,8,9} } (etc...) 
} 

等。为了简洁起见,我留下了上述简短的内容,但我希望这很明显,我正试图构建一个“树”的数据,我从一个带有静态数据的API调用开始(客户的ID),然后从那里制作使用API​​响应中的内容进行调用。

我知道延迟执行的承诺,$ q.all,。那么,等等等等,但是,一切都我只是试着让我兜兜转转。忘记即使制作漂亮的小巧功能来处理每一点。我了解基础知识,但是我从来没有见过如何组装复杂事物的实际实例。

有人可以帮助我了解如何处理多个异步操作,其中每一个依赖于面前的一个结果?特别是在多个异步操作必须在各种循环中调用并在继续之前完成的情况下?

我已经在PHP等服务器端语言中做过类似的事情,但这些很简单,直到当前操作完成后代码才会前进。

我会发布一些我尝试过的代码,但这是一个总的笑话。

谢谢。

+0

使用'promises'。你可以检查这个:https://docs.angularjs.org/api/ng/service/$http 如果你还可以使用'$ resource'。 – batmaniac7

+0

正如你所说的发布你的代码,也许它有帮助。 – developer033

回答

0

您可以使用promises 考虑调用API第一

someService.getCustomer().then(response => { 
    // call next api 
    someService.getOrders().then(resp =>{ 
       // call next api and so on 
    }); 
}); 

P.S:我假设你有角的代码。

+0

我已经看到了所有。这对于像这样复杂的事情没有帮助,在循环内部有API查找,并且在继续之前必须等待每个循环完成。 – user3565424

+0

你必须等到你知道你在找什么。不知道你如何跳过这一点。如果你一次性拥有所有必要的数据。 – batmaniac7

+0

此外,这样做(即使它工作),最终会产生一大套嵌套.then's。至少有四个,不要忘记其中大部分会有循环。我认为这是符合反模式的。 我需要弄清楚如何做到这一点,每一步都是自己的功能。每个按顺序调用,返回其数据,然后才调用下一个函数。 – user3565424

0

我不是很有经验的角度,我可能犯了一些错误,但如果这是我的项目,我会尝试以下方式:

创建模块

var app = angular.module('yourApp', []); 

创建服务所谓的聚合

app.factory('aggregator', ['$q', function($q) { 
    var aggregator = {}; 

    // object properties and method here 

    return aggregator; 
]}; 

应该能够做到以下操作:

aggregator.getCustomer = function(customerID) { 
    // this is where you would implement calls to your api 
    // however, as api calls take long, it is a good place to use 
    // a promise because you can sort of synchronize asynchronous functions this way 
    // before returning the promise, you need to define what happens 
    // when you receive some response 
    // implementation further down the answer 
}; 

aggregator.getCustomerPreviousOrders = function(customerID) { 
    // implementation to follow 
}; 

aggregator.getOrderedProducts = function(orderIDsArray) { 
    // implementation to follow 
}; 

aggregator.getRelated = function(productID) { 
    // implementation to follow 
}; 

这些方法中的每一个都应该返回一个promise,并且它的工作方式几乎相同,无论您调用的是哪个API部分。

例如,让顾客可以做这样的:

aggregator.getCustomer = function(customerID) { 
    // make sure you have injected $q 

    // first you create an object that will be able to: 
    // 1. promise your customer data to another object 
    // 2. call api 
    // 3. if result returned from api call is positive, it passes the results to the object it made the promise to 
    // 4. if result is negative, it rejects the promise it made before, 
    // thus, still providing some answer 
    // With $q, you create this object by calling $q.defer() 
    var result = $q.defer(); 

    // Then you make your api call 
    $http({ 
       method: 'GET' 
       ,url: 'api/customer' 
       ,params: { id: customerID } 
     }).then(function callbackSuccess(response) { 

      result.resolve(response); // in success callback you resolve and include the response in promise resolution. When this happens, you will be able to proceed to the next api call 

     }, function callbackError(error) { 

      result.reject(error) // in error callback you reject and include the error in promise rejection. When this happens you will stop your chain of api calls and get an error which you can handle nicely 

     }); 



    // Then, as you will reach the end of this function before you receive api response, you must return a promise, so that the object that called this getCustomer function can hold on to something at least 
    return result.promise; 

} 

然后定义使用相同原理的所有其他功能,然后您可以链接在你的控制器来使用这些API调用,就像这样:

app.controller('someController', ['$scope', 'aggregator', function($scope, aggregator) { 

    $scope.onCustomerSelected = function(id) { 
     $scope.customerID = id; 
    } 

    $scope.loadData = function() { 
     // in here you can chain your aggregator functions 
     aggregator.getCustomer($scope.customerID) // wherever your customerID comes from 
     .then(aggregator.getCustomerPreviousOrders(response)) 
     .then(aggregator.getOrderedProducts(response)) 
     .then(aggregator.getRelated(response)) 
     .then(function(response) { 
      // here you finally handle your response with all the collected data 
     }) 
     .catch(function(response) { 
      // here you handle any errors that come up in the chain of api calls 
      // whichever call ends up with an error will be handled by this handler and that is one elegant way to handle errors 
     }); 
    } 

    $scope.loadData(); 
}]); 

编辑 - 随便逛逛,我发现更多的选择here。看看,我希望它会有所帮助。