2016-05-16 15 views
0

約束事でページ付けされたAPIを呼びたいと思います。利用可能なページ数の情報は、最初は分かっていませんが、すべての応答で配信されます。具体的には、私はJiraのsearchを呼び出しています、ページング情報の一部は次のようになります。私は再帰とページネーションの取り扱いを解決約束事でページ付けされたAPIを呼び出す

{ 
    "startAt": 0, 
    "maxResults": 15, 
    "total": 100000, 
    ... 
} 

、これは活字体で私のソリューションです:

search(jql: string, fields: string[] = [], maxResults = 15) : Promise<JiraIssue[]> { 
    // container for the issues 
    let issues: Array<JiraIssue> = new Array<JiraIssue>(); 

    // define recursive function to collect the issues per page and 
    // perform a recursive call to fetch the next page 
    let recursiveFn = (jql: string, fields: string[], startAt: number, maxResults: number) : 
     Promise<JiraIssue[]> => { 
     return this 
      // retrieves one page 
      .searchPage(jql, fields, startAt, maxResults) 
      .then((searchResult: JiraSearchResult) => { 
       // saves the result of the retrieved page 
       issues.push.apply(issues, searchResult.issues); 
       if (searchResult.startAt + searchResult.maxResults < searchResult.total) { 
        // retrieves the next page with a recursive call 
        return recursiveFn(jql, fields, 
         searchResult.startAt + searchResult.maxResults, 
         maxResults); 
       } 
       else { 
        // returns the collected issues 
        return issues; 
       } 
      }) 

    }; 

    // and execute it 
    return recursiveFn(jql, fields, 0, maxResults); 
} 

しかし、I再帰的なアプローチが気に入らないのは、小さな結果セットでのみうまくいくからです(私はスタックオーバーフローを恐れています)。どのように再帰的なアプローチでこの問題を解決しますか?

+1

これは実際の再帰ではなく、関数がその中で呼び出されているため、スタックオーバーフローの危険はありません。 –

答えて

2

これは実際の再帰ではなく、thenハンドラ内で関数が呼び出されているため、スタックオーバーフローの危険はありません。

1

1つのオプションは、イテレータパターンでこれをラップすることです。

ような何か:私はあなたがそこに何をしているのか全くわからないよう

interface Searcher { 
    (jql: string, fields: string[], startAt: number, maxResults: number) => Promise<JiraSearchResult>; 
} 

class ResultsIterator { 
    private jql: string; 
    private fields: string[]; 
    private searcher: Searcher; 
    private startAt: number; 
    private maxResults: number; 
    private currentPromise: Promise<JiraIssue[]>; 
    private total: number; 

    constructor(searcher: Searcher, jql: string, fields?: string[], maxResults?: number) { 
     this.jql = jql; 
     this.startAt = 0; 
     this.searcher = searcher; 
     this.fields = fields || []; 
     this.maxResults = maxResults || 15; 
     this.total = -1; 
    } 

    hasNext(): boolean { 
     return this.total < 0 || this.startAt < this.total; 
    } 

    next(): Promise<JiraIssue[]> { 
     if (!this.hasNext()) { 
      throw new Error("iterator depleted"); 
     } 

     return this.searcher(this.jql, this.fields, this.startAt, this.maxResults) 
        .then((searchResult: JiraSearchResult) => { 
         this.total = searchResult.total; 
         this.startAt = searchResult.startAt + searchResult.maxResults; 

         return searchResult.issues; 
        }); 
    } 
} 

このコードは、完璧ではない(例えばthis.searchPageは何ですか?)、しかし、あなたはおそらくアイデアIを取得する必要があります〜を目指しています。

あなただけやる:

if (resultIterator.hasNext()) { 
    resultIterator.next().then(...); 
} 

は、この情報がお役に立てば幸いです。

関連する問題