簡體   English   中英

附加到帶有遞歸承諾的數組,JavaScript

[英]Append to array with recursive promises, Javascript

我正在嘗試編譯從多個API調用中獲得的數據列表,但是在建立數組和陷入無限遞歸時遇到了問題。

調用遞歸函數的函數:

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

我相信我正確地處理了基本情況,但是,如果必須多次調用查詢,這意味着2級遞歸,則只會打印最新的遞歸調用返回值。 數組輸出將被覆蓋。如果不滿足基本條件,如何處理數據?

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. slice應該用作slice(1)來工作

您應該將較新的結果連接到已有的結果上。 因此,在最后幾行中,您將不會使用newData進行解析,而是使用output.concat(newData)進行output.concat(newData) 另外,在這里push是錯誤的...您需要concat

應該提到的是,您正在應用promise構造函數的反模式,即在已經可以使用的promise中創建一個promise。 不需要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);
      })
  })
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM