0

So here is my problem (and I have tried several suggestions found here at stackOverflow):

Scenario:

I am using the Gitlab API and I want to list all the "issues" of the bug tracker present on the system for a given project.


Problem:

This is all fine and good, however there is a paging system to do this since the ajax requesst is limited to 100 entries per response.

So I have to do something like this:

$.ajax({
    url: "https://mygitlabURL/api/v3/projects/97/issues",
    type: "GET",
    data: {
        private_token: "mytoken",
        per_page: 100,
        page: 1
    }

This will give me back 100 entries. What I need to do is add these entries to a list, and check: "was there fewer than 100 entries in the response?" if so I can stop doing requests.

I need however to get the complete list before I can move on with my code, so I tried using $.when() function and do my requests in a function of its own. In this function I have tried using:

  • closures like in this answer
  • recursion like suggested in another answer (don't have the link)
  • while loop since, oh well, why not

The problem with all the solutions is that, beeing asynchronous, I end up receiving a response and my $.when() function executes before I have any response from the server.

Is there a way to do this?

Here is the latest code (with recursion) I have tried:

$(function () {
    $("button").on("click", function () {
        $.when(func1(), func2()).then(finishedFunc);
    });
});

var func1 = function (pageNr) {
    pageNr = pageNr || 1;

    megaList = [];
    // Get server values
    $.ajax({
        url: "https://mygitlabURL/api/v3/projects/97/issues",
        type: "GET",
        data: {
            private_token: "myToken",
            per_page: 100,
            page: pageNr
        },
        success: function (issuesList) {
            console.log("Page number: " + pageNr);

            megaList = [pageNr];

            if (issuesList.length < 100) {
                return megaList;
            }

            pageNr = pageNr +1 ;
            var received = func1(pageNr);
            megaList = $.merge(megaList, received);

            return megaList;
        }
    });
  }

var func2 = function () { 
    return 20;
}

var finishedFunc = function (resp1, resp2) {
    console.log("Responses were resp1: " + resp1 + " and resp2: " + resp2);
}

And I always get something like: "Responses were resp1: undefined and resp2: 20"

And I am expecting something like: "Responses were resp1: [1, 2, 3, 4, 5, ..., 27] and resp2: 20"

As stated before, I can't find any solutions that resolve my problem here in the forums, but if I might have overlooked something, please point me in the right way.

Community
  • 1
  • 1
fditz
  • 871
  • 9
  • 28
  • From this line `var received = func1(pageNr);` I see you think that returning value inside `success` handler will result to returning value from `func1`. But this is not so. You cannot to do so since `ajax` is **asynchronous** – hindmost Mar 03 '15 at 09:52

2 Answers2

1

While reading the documentation.I came across this. Pagination

When listing resources you can pass the following parameters:

page (default: 1) - page number
per_page (default: 20, max: 100) - number of items to list per page

Link headers are send back with each response. These have rel prev/next/first/last and contain the relevant URL. Please use these instead of generating your own URLs.

It automatically says that the Response that came back will contain rel prev/next/first/last. So you can easily check that link headers contain next rel or not and If it contain then directly call that url for more issues and If not that means it does not contain more issues.

Innovation
  • 1,514
  • 17
  • 32
  • I am aware of that, unfortunately these link headers are not easy to get when workinf with jquery ajax. I have tried and can not get those. Plus it would still leave me the problem of waiting for the complete list before returning to the program flow – fditz Mar 03 '15 at 09:51
  • Use html5 web workers for running them in backend. Also you can easily get response headers by issuesList.getResponseHeader('prev') & issuesList.getResponseHeader('next') .You make first request and then run everything in while lopp till the next header is empty. – Innovation Mar 03 '15 at 09:55
  • Doing a while loop ends up blocking the code similarly to a async ajax request. And I would like to avoid that since I want to display some feedback to the user. – fditz Mar 03 '15 at 09:59
  • Just tested : issuesList.getResponseHeader('prev') renders: "Uncaught TypeError: undefined is not a function" and using something like: function(data, textStatus, request){ alert(request.getResponseHeader('prev')); } also doesn't help. They cannot be found with ajax – fditz Mar 03 '15 at 09:59
  • I will give a go and then give some feedback. Thanks – fditz Mar 03 '15 at 10:01
  • Please use firebug plugin in firefox and post request and response that is coming then I will be able to get the exact idea about how the headers are coming.I think you will get Link headers by using issuesList.getResponseHeader('Link') then you will get list of links and there rel attribute will tell you about the url for next or prev. – Innovation Mar 03 '15 at 10:08
  • Check this.May be it will help you https://developer.github.com/guides/traversing-with-pagination/ – Innovation Mar 03 '15 at 10:10
  • There is no point in using web workers for this. Web workers are for cpu-bound operations, not I/O-bound operations. – JLRishe Mar 03 '15 at 10:27
  • There is a clear cut solution using git API link headers and web workers.Try to read more about them.You will definitely find the right way. Don't just go on theory. Check why we use web workers .At every page create new web worker and use current web worker for showing something to user.Web workers use for background process and does not let user to wait for javascript run completion. – Innovation Mar 03 '15 at 10:35
1

Once you start to think in async terms the solution become pretty simple:

var megaList = [];
function loadList(page) {
    page = Math.max(1, page);
    $.ajax({
        url: "https://mygitlabURL/api/v3/projects/97/issues",
        type: "GET",
        data: {
            private_token: "myToken",
            per_page: 100,
            page: page
        },
        success: function (issuesList) {
            console.log("Page number: " + page);
            megaList = megaList.concat(issuesList);
            if (issuesList.length >= 100) loadList(page+1);
        }
    });
}
loadList();
hindmost
  • 7,125
  • 3
  • 27
  • 39
  • I think that should actually be `if (issuesList.length < 100)` – JLRishe Mar 03 '15 at 10:22
  • @ JLRishe According to the OP's specs (`check: "was there fewer than 100 entries in the response?" if so I can stop doing requests`) it should be `if (issuesList.length >= 100)` – hindmost Mar 03 '15 at 14:08