我已经不知道我尝试过多少次这项工作了。我只是不明白。
让我假装我有以下API调用:
API /客户(CUST)
API /订单(订单ID)
API /产品(产品ID)
API /相关(relatedid)
完成所有操作后,我需要一个包含所有数据的对象作为数组和子数组(将在下面解释)。
我需要首先对api / customer进行api调用。返回将是客户的先前订单作为对象数组。让我们假装他们订了三个订单。
每个对象内部都有各种键:值对,包括一个名为" products"这本身就是一系列生产数字。
现在我必须遍历所有产品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...)
}
等等。我为了简洁而留下了上述简称,但我希望很明显我正在努力建造一棵树#34;""我从一个带有静态数据的API调用(客户的id)开始,然后从那里开始,使用API响应中的内容进行调用。
我知道延期承诺,$ q.all,.then等等。但是我尝试的一切都让我绕圈子走了。忘掉甚至制作漂亮的紧凑功能来处理每一位。我理解基础知识,但我从未见过如何组装复杂事物的真实世界范例。
有人可以帮助我理解如何处理多个异步操作,其中每个异步操作都依赖于之前的结果吗?特别是在必须在各种循环中调用多个异步操作并在继续之前完成的情况下?
我已经在像PHP这样的服务器端语言中完成了这样的事情,但是当代码不会推进直到当前操作完成时,这些都很容易。
我发布了一些我尝过的代码,但这只是一个笑话。
谢谢。
答案 0 :(得分:0)
您可以使用promises
考虑先调用api
someService.getCustomer().then(response => {
// call next api
someService.getOrders().then(resp =>{
// call next api and so on
});
});
P.S:我假设你有角度代码。
答案 1 :(得分:0)
我对Angular不是很有经验,我可能犯了一些错误,但如果这是我的项目,我会尝试以下方式:
创建模块
var app = angular.module('yourApp', []);
创建名为aggregator的服务
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
};
这些方法中的每一种都应该返回一个承诺,它的工作方式几乎相同,不管你调用的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。看看,我希望它会有所帮助。