2016-07-07 61 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。看看,我希望它會有所幫助。