2017-10-28 99 views
0

我想編譯一個數據列表,我從多個API調用中獲得的數據,但有問題與構建陣列和陷入無限遞歸。追加數組與遞歸承諾,Javascript

函數調用遞歸函數:

jsonToCsv() { 
    this.exportCSV().then(data => { 
    console.log('From jsonToCSV', data) 
    }) 
} 

遞歸函數

exportCSV (uidList = this.checkboxList.slice(), offset = 0) { 
    // Get query, build request 
    let request = { 
    id: 'export', 
    query: this.currentQuery.query, 
    sort: this.currentQuery.sort, 
    limit: 100, // how much data is returned 
    offset: offset // pagination value 
    } 

    return new Promise((resolve, reject) => { 

    // using Vuex to fetch data, returns an array of objects. 
    this.$store.dispatch('show/fetchQuery', request).then(data => { 
     let headerList = this.shownHeaders // an array of column id's & thier 'nice names' 
     let output = [] 
     let row, uid, header 

     // match the id's to the Data from the API call 
     for (uid = 0; uid < uidList.length; uid++) { 
     for (row = 0; row < data.length; row++) { 
      if (data[row].uid === uidList[uid]) { 
      let rowData = {} 
      uidList.splice(uid, 1) // found this id so remove from list 

      // take data from query call that we want, make objects, push them to array 
      for (header = 0; header < headerList.length; header++) { 
       let niceName = headerList[header].niceName 
       let id = headerList[header].id 
       rowData[niceName] = data[row][id] 
      } 
      output.push(rowData) 
      } 
     } 
     } 

     // Basecase 
     if (uidList.length === 0) { 
     resolve(output) 
     return 
     } 

     offset += 100 // get next 100 results from query 
     // run next recursive call 
     this.exportCSV(uidList, offset).then(newData => { 
     output.push(newData) 
     resolve(newData) 
     }) 
    }) 
    }) 

我相信我正確處理basecase,但是,如果查詢被稱爲多比一次,意味着2級遞歸,只有最新的遞歸調用返回值被打印出來。數組輸出被覆蓋..如果不滿足basecase,我該如何處理解析數據?

回答

0
var exportCSV = (uidList = this.checkboxList.slice(1), offset = 0) => { 
     return new Promise(function(resolveFinal){ 
        var rec = (uidListTemp = uidList, offsetTemp = offset, output = [])=>{ 
        let request = { 
        id: 'export', 
        query: this.currentQuery.query, 
        sort: this.currentQuery.sort, 
        limit: 100, // how much data is returned 
        offset: offset // pagination value 
        } 

        return new Promise((resolve, reject) => { 

        // using Vuex to fetch data, returns an array of objects. 
        this.$store.dispatch('show/fetchQuery', request).then(data => { 
         let headerList = this.shownHeaders // an array of column id's & thier 'nice names' 
         let row, uid, header 

         // match the id's to the Data from the API call 
         for (uid = 0; uid < uidList.length; uid++) { 
         for (row = 0; row < data.length; row++) { 
          if (data[row].uid === uidList[uid]) { 
          let rowData = {} 
          uidList.splice(uid, 1) // found this id so remove from list 

          // take data from query call that we want, make objects, push them to array 
          for (header = 0; header < headerList.length; header++) { 
           let niceName = headerList[header].niceName 
           let id = headerList[header].id 
           rowData[niceName] = data[row][id] 
          } 
          output.push(rowData) 
          } 
         } 
         } 

         resolve(output); 
       }).then(output=>{ 
         //base case 
         if (uidList.length === 0) { 
           resolveFinal(output); 
           return output; 
          } else { 
         offset += 100 // get next 100 results from query 
         // run next recursive call 
         rec(uidList, offset, output) 
        } 
         }); 
        }); 
        } 
        rec(); 
       }) 
      } 
  1. 使用輸出所有REC調用,而不是在每一個REC呼叫作出新的輸出實例共享。
  2. 使用2承諾一個最終響應和其他中間響應。
  3. 片應作爲片(1)工作
0

你應該串聯更新的結果你已經擁有的。所以在最後一行你不會用newData來解決,但是用output.concat(newData)。此外,push在這裏是錯誤的...你需要concat

應該提及的是,您正在應用承諾構造函數antipattern,即您已經創建了一個可以使用的承諾。不需要new Promise

這裏是如何可能看起來:

exportCSV (uidList = this.checkboxList.slice(), offset = 0) { 
    // Get query, build request 
    let request = { 
    id: 'export', 
    query: this.currentQuery.query, 
    sort: this.currentQuery.sort, 
    limit: 100, // how much data is returned 
    offset: offset // pagination value 
    } 

    // using Vuex to fetch data, returns an array of objects. 
    // (don't create a new promise when can return an existing one) 
    return this.$store.dispatch('show/fetchQuery', request).then(data => { 
     // Basecase 
     if (uidList.length === 0) { 
     return []; 
     } 

     let headerList = this.shownHeaders // an array of column id's & thier 'nice names' 
     let output = [] 
     let row, uid, header 

     // match the id's to the Data from the API call 
     for (uid = 0; uid < uidList.length; uid++) { 
     for (row = 0; row < data.length; row++) { 
      if (data[row].uid === uidList[uid]) { 
      let rowData = {} 
      uidList.splice(uid, 1) // found this id so remove from list 

      // take data from query call that we want, make objects, push them to array 
      for (header = 0; header < headerList.length; header++) { 
       let niceName = headerList[header].niceName 
       let id = headerList[header].id 
       rowData[niceName] = data[row][id] 
      } 
      output.push(rowData); 
      // Probably you can now break out of this loop as you 
      // will not expect a second match 
      break; 
      } 
     } 
     } 

     // run next recursive call, return the promise 
     return this.exportCSV(uidList, offset + 100).then(newData => { 
     // append to previous results 
     return output.concat(newData); 
     }) 
    }) 
}