2017-10-28 6 views
0

Ich versuche, eine Liste der Daten zu kompilieren, die ich von mehreren API-Aufrufe bekomme, aber Probleme mit dem Aufbau des Arrays und in der unendlichen Rekursion gefangen.Append an Array mit rekursiven Versprechen, Javascript

Funktion, die die rekursive Funktion aufruft:

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

rekursive Funktion

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) 
     }) 
    }) 
    }) 

Ich glaube, ich das Basecase richtig bin Handhabung jedoch, wenn die Abfrage namens mehr werden muss als einmal, was 2 Rekursionsebenen bedeutet, wird nur der Rückgabewert der letzten rekursiven Aufrufe gedruckt. Die Array-Ausgabe wird überschrieben. Wie behebe ich die Auflösung der Daten, wenn der Basisfall nicht erfüllt ist?

Antwort

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. Verwendung Ausgabe in allen rec Anrufen geteilt, anstatt eine neue Ausgabeinstanz in jedem rec Anruf zu machen.
  2. Verwenden Sie 2 verspricht eine für die endgültige Antwort und andere für Zwischenreaktionen.
  3. Scheibe sollte als Scheibe (1) verwendet werden
0

Sie die neueren Ergebnisse, die Sie schon mussten die, die verketten sollten arbeiten. In den letzten Zeilen würde man also nicht mit den newData auflösen, sondern mit output.concat(newData). Auch push ist hier falsch ... Sie brauchen concat.

Es sollte erwähnt werden, dass Sie den Verhinderer Konstruktor Antipattern anwenden, d. H. Sie erstellen ein Versprechen, wo es bereits eine gibt, die Sie verwenden können. Es ist kein new Promise erforderlich.

Hier ist, wie es aussehen könnte:

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); 
     }) 
    }) 
}