2017-04-03 1 views
1

Ich habe hier eine einzigartige Situation, die ich auf elegante Weise nicht lösen kann.Mit KnexJS X-Anzahl von Tabellen abfragen?

Ein Benutzer übergibt ein Array von Signalen, für die er Daten exportieren möchte. Dieses Array kann 1 -> Any_Number sein, also gehe ich zuerst die Tabellennamen holen (jedes Signal speichert Daten in einer separaten Tabelle) basierend auf den übertragenen Signalen und speichere diese in einem Objekt.

Der nächste Schritt besteht darin, über dieses Objekt zu iterieren (das die Tabellennamen enthält, die abgefragt werden müssen), die Abfrage pro Tabelle auszuführen und die Ergebnisse in einem Objekt zu speichern, das an die nächste Kette in der Promise übergeben wird. Ich habe online keine Beispiele dafür gesehen, wie man damit umgehen kann, aber ich weiß, dass es ein ziemlich einzigartiges Szenario ist.

Mein Code vor dem Versuch Unterstützung für Arrays von Signalen hinzuzufügen wurde einfach folgendes:

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

    var getTableName = function() { 
     return knex('monitored_parameter') 
     .where('device_id', data.device_id) 
     .andWhere('internal_name', data.param) 
     .first() 
     .then(function(row) { 
      if(row) { 
      var resp = {"table" : 'monitored_parameter_data_' + row.id, "param" : row.display_name}; 
      return resp; 
      } 
     }); 
    } 

    var getData = function(runningResult) { 
     return knexHistory(runningResult.table) 
     .select('data_value as value', 'unit', 'created') 
     .then(function(rows) { 
      runningResult.data = rows; 
      return runningResult; 
     }); 
    } 

    var createFile = function(runningResult) { 

     var fields = ['value', 'unit', 'created'], 
      csvFileName = filePathExport + runningResult.param + '_export.csv', 
      zipFileName = filePathExport + runningResult.param + '_export.gz'; 

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

     fs.writeFileSync(csvFileName, csv); 

     // create streams for gZipping 
     var input = fs.createReadStream(csvFileName); 
     var output = fs.createWriteStream(zipFileName); 

     // gZip 
     input.pipe(gzip).pipe(output); 

     return zipFileName; 

    } 

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

Offensichtlich das funktioniert für eine einzelne Tabelle in Ordnung und ich habe die getTableName() und Createfile() Methoden aktualisiert bekommen um Datenfelder zu behandeln, so bezieht sich diese Frage nur auf die Methode getData().

Prost!

Antwort

1

Diese Art von Problem ist alles andere als einzigartig und auf den richtigen Weg, ist sehr einfach gelöst.

Keine der drei internen Funktionen neu schreiben.

Löschen Sie einfach die explicit promise construction antipattern von .getRawDataForExport(), so dass es eine natürlich vorkommende Versprechen zurückgibt und asynchrone Fehler an den Aufrufer weiterleitet.

return getTableName() 
.then(getData) 
.then(createFile); 

Nun sind .getRawDataForExport() die grundlegenden Baustein für Ihr mehrfachen „bekommt“.

Dann eine Design-Wahl; parallele versus sequenzielle Operationen. Beide sind sehr gut dokumentiert.

Parallel:

exports.getMultiple = function(arrayOfSignals) { 
    return Promise.all(arrayOfSignals.map(getRawDataForExport)); 
}; 

Sequential:

exports.getMultiple = function(arrayOfSignals) { 
    return arrayOfSignals.reduce(function(promise, signal) { 
     return promise.then(function() { 
      return getRawDataForExport(signal); 
     }); 
    }, Promise.resolve()); 
}; 

In erster Linie für die beste mögliche Leistung, versuchen parallel.

Wenn der Server bei parallelen Vorgängen gedrosselt wird oder wahrscheinlich gedrosselt wird, wählen Sie sequenziell.

+0

Das ist ein großartiger Ratschlag und ich habe das Gefühl, dass es mir ganz neue Türen öffnen könnte, wenn es darum geht, diese Art von Ereignissen in JS zu behandeln ... Könntest du ein wenig mehr über die ersten Dinge, die du erwähnst, erzählen? Ein kurzes Beispiel, das zeigt, wie man das Antipattern bricht und wo die Entschlossenheit/Zurückweisung geschieht, wäre hilfreich. Die Art, wie ich es gesehen habe .GetRawDataForExport() gab bereits eine Versprechung zurück, ist das nicht der Fall? Danke noch einmal! –

+1

@NicholasKreidberg, sorry mein Schlechter. Sie haben tatsächlich bereits ein Versprechen abgegeben. Bearbeitete Wörter sollten mehr Sinn ergeben. –

Verwandte Themen