How to make a clean asynchronous loop?

Following typical REST standards, I have broken down my resources into separate endpoints and calls. There are two main objects: List and Item (and, of course, the list has a list of elements, as well as some other data associated with it).

Therefore, if the user wants to get his lists, he can make a Get request on api/Lists

Then the user may want to get items in one of these lists and do Get to api/ListItems/4 , where 4 was found from List.listId retrieved in the previous call.

This is good and good: the options.complete $.ajax allows me to point to a callback method, so I can optimize these two events.

But everything becomes very dirty if I want to get items for all the lists in question. For example, suppose I have a library function called makeGetRequest that accepts an endpoint and callback function to make this code cleaner. Simple extraction of 3 elements in a naive way leads to the following:

 var success1 = function(elements){ var success2 = function(elements){ makeGetRequest("api/ListItems/3", finalSuccess); } makeGetRequest("api/ListItems/2", success2); } makeGetRequest("api/ListItems/1", success1); 

Disgusting! This is what we talk about in programming 101, we press the wrists and point the loops. But how can you do this with a loop without relying on external storage?

 for(var i : values){ makeGetRequest("api/ListItems/" + i, successFunction); } function successFunction(items){ //I am called i-many times, each time only having ONE list worth of items! } 

And even with the repository, I would have to know when everyone had finished and retrieved their data, and call some main function that retrieves all the collected data and does something with it.

Is there any practice for this? This must have been allowed many times before ...

+6
source share
2 answers

Try using the endpoint parameter stack:

 var params = []; var results []; params.push({endpoint: "api/ListItems/1"}); params.push({endpoint: "api/ListItems/2"}); params.push({endpoint: "api/ListItems/3"}); params.push({endpoint: "api/ListItems/4"}); 

You can then make it recursive in your success handler:

 function getResources(endPoint) { var options = {} // Ajax Options options.success = function (data) { if (params.length > 0) { results.push({endpoint: endpoint, data: data}); getResources(params.shift().endpoint); } else { theMasterFunction(results) } } $.get(endPoint, options) } 

And you can start it with one call:

 getResources(params.shift().endpoint); 

Edit:

To save everything yourself and outside the global scope, you can use the function and provide a callback:

 function downloadResources(callback) { var endpoints = []; var results []; endpoints.push({endpoint: "api/ListItems/1"}); endpoints.push({endpoint: "api/ListItems/2"}); endpoints.push({endpoint: "api/ListItems/3"}); endpoints.push({endpoint: "api/ListItems/4"}); function getResources(endPoint) { var options = {} // Ajax Options options.success = function (data) { if (endpoints.length > 0) { results.push({endpoint: endpoint, data: data}); getResources(endpoints.shift().endpoint); } else { callback(results) } } $.get(endPoint, options) } getResources(endpoints.shift().endpoint); } 

Using:

 downloadResources(function(data) { // Do stuff with your data set }); 
+4
source

Dmck's answer is probably the best choice. However, another option is to execute the bulk list option so that your api supports queries like api / ListItems /? Id = 1 & id = 2 & id = 3.

You can also use the api search endpoint if it is more suitable for your personal aesthetics.

+2
source

Source: https://habr.com/ru/post/921979/


All Articles