2017-04-12 2 views
1

Ich bin ziemlich neue Versprechen und dachte, ich hätte einen Griff auf Dinge, aber klar ich nicht.Promise Chain Breaks w/.all()

Der folgende Code soll die X-Nummer der Tabellennamen (getTableName()) erfassen, diese an getData() übergeben und eine Schleife über jede Tabelle ziehen, um die Daten zu erhalten. Ich rufe dann Promise.all() auf, um diese aufzulösen und zu versuchen, die Daten an den nächsten Link in der Kette (createFile()) weiterzuleiten, aber Promise.all() wird aufgelöst, nachdem es zu createFile() übergegangen ist.

Ist dies ein Beispiel für das "Antipattern", das mich zurückhält? Wenn ja, können Sie mir vorschlagen, wie ich umstrukturieren sollte, damit ich erreichen kann, was ich vorhabe?

Danke!

exports.getRawDataForExport = function(data) { 
    return new Promise(function(resolve, reject) { 

    var getTableName = function() { 
     return knex('monitored_parameter') 
     .where('device_id', data.device_id) 
     .whereIn('internal_name', data.param) 
     .select() 
     .then(function(rows) { 
      if(rows) { 
      var runningResult = {}; 
      for(var i = 0; i < rows.length; i++) { 
       var tbl = {"table" : 'monitored_parameter_data_' + rows[i].id, "param" : rows[i].display_name}; 
       runningResult.table = []; 
       runningResult.table.push(tbl); 
      } 

      return runningResult; 

      } else { 
      // if no MP row(s) found we cannot proceed 
      throw new Error("No history found for that parameter."); 
      } 
     }); 
    } 

    var getData = function(runningResult) { 
     var promises = []; 

     if(data.date_start && data.date_end) { 
     // grab within range 

     for(var i = 0; i < runningResult.table.length; i++) { 
      promises.push(
      knexHistory(runningResult.table[i].table) 
       .select('created', 'data_value as value', 'unit') 
       .whereBetween('created', [data.date_start, data.date_end]) 
      ); 
     } 

     // *** the chain moves on to createFile() before this data is passed along 
     Promise.all(promises).then(function(data) { 
      console.dir('inside promises.all'); 
      console.dir(data); 
      runningResult.data = data; 
      return runningResult; 
     }); 

     } else { 
     // grab all 
     for(var i = 0; i < runningResult.table.length; i++) { 
      promises.push(
      knexHistory(runningResult.table[i].table) 
       .select('created', 'data_value as value', 'unit') 
      ); 
     } 

     // *** the chain moves on to createFile() before this data is passed along 
     Promise.all(promises).then(function(data) { 
      console.dir('inside promises.all'); 
      console.dir(data); 
      runningResult.data = data; 
      return runningResult; 
     }); 
     } 
    } 

    var createFile = function(runningResult) { 

     var files = [], 
      zipFileName = filePathExport + 'Data_Export.zip'; 

     for(var i = 0; i < runningResult.table.length; i++) { 
     var fields = ['created', 'value', 'unit'], 
      csvFileName = runningResult.param + '_export.csv', 
      csvFilePath = filePathExport + runningResult.param + '_export.csv'; 

     var csv = json2csv({data : runningResult.data[i], fields : fields, doubleQuotes : ''}); 

     fs.writeFileSync(csvFilePath, csv); 

     files.push(csvFilePath); 
     } 

     var zip = new admzip(); 

     for(var j = 0; j < files.length; j++) { 
     var input = fs.readFileSync(files[i]); 
     zip.addFile(csvFileName, input, '', 0644); 
     } 

     zip.writeZip(zipFileName); 

     return zipFileName; 

    } 

    getTableName() 
     .then(getData) 
     .then(createFile) 
     .then(function(zipFile) { 
     resolve(zipFile); 
     }) 
     .catch(function(err) { 
     resolve(err); 
     }); 

    }); 
} 

Antwort

4

Sie müssen das Ergebnis der Promise.all(...).then(...) (in beiden Fällen) return, so dass getData ein Versprechen zurück.

Und ja, Sie verwenden die promise constructor antipattern, obwohl es nicht die Ursache des Problems ist.

Entfernen Sie die return new Promise(function(resolve, reject) { Wrapper und kehren nur wie folgt aus:

return getTableName().then(getData) 

... die Anrufe resolve

+0

Danke für die schnelle Antwort, dieser Ansatz funktioniert großartig. –

1

Sie wahrscheinlich nur Promise.all die ketten return wollen Weglassen

var getData = function(runningResult) { 
     var promises = []; 

     if(data.date_start && data.date_end) { 
     // grab within range 

     for(var i = 0; i < runningResult.table.length; i++) { 
      promises.push(
      knexHistory(runningResult.table[i].table) 
       .select('created', 'data_value as value', 'unit') 
       .whereBetween('created', [data.date_start, data.date_end]) 
      ); 
     } 

     // *** the chain moves on to createFile() before this data is passed along 
     return Promise.all(promises).then(function(data) { 
      console.dir('inside promises.all'); 
      console.dir(data); 
      runningResult.data = data; 
      return runningResult; 
     }); 

     } else { 
     // grab all 
     for(var i = 0; i < runningResult.table.length; i++) { 
      promises.push(
      knexHistory(runningResult.table[i].table) 
       .select('created', 'data_value as value', 'unit') 
      ); 
     } 

     // *** the chain moves on to createFile() before this data is passed along 
     return Promise.all(promises).then(function(data) { 
      console.dir('inside promises.all'); 
      console.dir(data); 
      runningResult.data = data; 
      return runningResult; 
     }); 
     } 
    }