2017-10-28 28 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回の再帰を意味し、最新の再帰呼び出しの戻り値のみが出力されます。配列の出力が上書きされます。ベースコードが満たされていない場合、データの解決はどのように処理しますか?代わりに、すべてのREC呼び出しで新しい出力インスタンスを作るのすべてのRECの呼び出しで共有

答えて

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. 使用出力。
  2. 2を使用すると、最終応答と中間応答の両方を約束します。
  3. スライスが
0

を動作するように(1)スライスとして使用する必要がありますあなたがすでに持っていたものに、新しい結果を連結する必要があります。だから最後の行では、output.concat(newData)とnewDataで解決できません。また、pushは間違っています...あなたはconcatが必要です。

プロミスコンストラクタの反パターンを適用している、つまり、すでに使用できるところに約束を作成するということに言及してください。 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); 
     }) 
    }) 
} 
関連する問題