2016-05-16 32 views
0

我想用承諾調用分頁API。有多少頁面可用的信息在開始時是未知的,但會在每個響應中傳遞。在細節我打電話一吉拉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); 
} 

然而,我不喜歡遞歸方法,因爲這隻適用於小結果集(我害怕堆棧溢出)。如何用非遞歸方法解決這個問題?

+1

這不是實際的遞歸,並且沒有堆棧溢出的危險,因爲函數在一個then中被調用。 – 2016-05-16 14:24:29

回答

2

這不是實際的遞歸,並且沒有堆棧溢出危險,因爲函數在then處理程序中被調用。

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?),但你應該得到的想法我我的目標是。

你只是做:

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

希望這有助於。