2016-06-02 9 views
2

Ich habe diese Ausschnitt des Arbeitscodes, die ich wirklich vereinfachen möchte. Es ist Ziel für Node.js v6.0 mit den Paketen bluebird & co. Dies ist eine typische Situation und ich möchte an den Punkt kommen, dass der Code kompakt und einfach zu verstehen ist, damit ich ihn in anderen Projekten wiederverwenden kann.Wie JS-Code mit verschachtelten Coroutinen und Versprechen zu vereinfachen?

Die Funktion gibt eine Checkliste mit einer Anzahl von Positionskategorien (1: m) zurück und jede Kategorie enthält eine Anzahl von Elementen (1: m: n). So ist es ein Objekt mit 2 verschachtelten Ebenen:

Root: Checklist 
    Level 1: Checklist Item Group(s) 
     Level 2: Checklist Item(s) 

Die Wurzelebene (1 Checkliste) und eine Ebene nach unten (Prüfliste Positionstypen) können durch Nachgeben in der Generatorfunktion implementiert werden.

Die 1: n: m Ebene kann nicht "Ausbeute" verwenden, wenn ich z. Promise.mapSeries() über Checkliste .__ node__ChecklistItemGroups, weil ein "Yield" nur in der Hauptgeneratorfunktion und nicht in der Map-Innenfunktion unterstützt wird. Also kehrte ich zurück zu der Funktion Promise.each() und einem Promise.then() Konstrukt. Diese

function getGraphChecklistById(pId) { 
    return co(function *() { 
     let checklist = yield getChecklistById(pId); // Returns a promise. 
     checklist.__node__ChecklistItemGroups = yield fetchChecklistItemGroupsByChecklistId(pId); // Returns a promise. 
     return checklist; 
    }) 
     .then(function (checklist) { 
      return Promise.each(
       checklist.__node__ChecklistItemGroups, 
       function (pItem) { 
        return fetchChecklistItemsByXrefId(pItem.xchlclig_id).then(function (result) { // fetchChecklistItemsByXrefId() returns a promise. 
         pItem.__node__ChecklistItems = result; 
        }); 
       }) 
       .then(function (unused) { 
        return checklist; 
       }); 
     }) 
} 

ist ein Beispiel Ergebnis:

result: { 
    "checklist-field-1": 1, 
    "checklist-field-2": 1, 
    "__node__ChecklistItemGroups": [ 
     { 
      "checklist-group-field-1": 1, 
      "checklist-group-field-2": 1, 
      "__node__ChecklistItems": [ 
       { 
        "checklist-item-field-1": 1, 
        "checklist-item-field-2": 1, 
       }, 
       { 
        "checklist-item-field-1": 2, 
        "checklist-item-field-2": 2, 
       } 
      ] 
     }, 
     { 
      "checklist-group-field-1": 2, 
      "checklist-group-field-2": 2, 
      "__node__ChecklistItems": [ 
       { 
        "checklist-item-field-1": 1, 
        "checklist-item-field-2": 1, 
       }, 
       { 
        "checklist-item-field-1": 2, 
        "checklist-item-field-2": 2, 
       } 
      ] 
     } 
    ] 
} 

Anregungen von einem Versprechen/Koroutinen-Experte? Vielen Dank für Ihre Zeit.

Antwort

4

ich es so schreiben würde - ohne Promise.each aber eine reine Schleife:

let getGraphChecklistById = Promise.coroutine(function*(pId) { 
//       ^^^^^^^^^^^^^^^^^ Don't put co(…) in a function, wrap directly 
    let checklist = yield getChecklistById(pId); 
    checklist.__node__ChecklistItemGroups = yield fetchChecklistItemGroupsByChecklistId(pId); // Returns a promise. 
    for (let pItem of checklist.__node__ChecklistItemGroups) { 
// ^^^ iteration in series like Promise.each does it 
     let result = yield fetchChecklistItemsByXrefId(pItem.xchlclig_id); 
//     ^^^^^ You can use yield here as it's not an extra function 
     pItem.__node__ChecklistItems = result; 
    } 
    return checklist; 
}); 

Ob die Verwendung Drossel Promise.coroutine oder co.wrap nicht wirklich hier Angelegenheit.

Und wenn man die Gruppen parallel iterieren möchten, können Sie immer noch yield in der Callback-Funktion verwenden, wenn Sie, dass ein Generator machen:

let getGraphChecklistById = Promise.coroutine(function*(pId) { 
    let checklist = yield getChecklistById(pId); 
    checklist.__node__ChecklistItemGroups = yield fetchChecklistItemGroupsByChecklistId(pId); // Returns a promise. 
    yield Promise.map(
     checklist.__node__ChecklistItemGroups, 
     Promise.coroutine(function*(pItem) { 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ pass this as the promise-returning callback function 
      let result = yield fetchChecklistItemsByXrefId(pItem.xchlclig_id); 
      pItem.__node__ChecklistItems = result; 
     }) 
    ); 
    return checklist; 
}); 
+0

Dank bergi für 50% der #lines Code Abschaben :) Der Hinweis ist in der Tat, dass eine For-of-Iteration keine innere Funktion benötigt. – Rolf

+0

Ich habe die empfohlenen Änderungen angewendet und das Co-Paket beibehalten. Endergebnis https://gist.github.com/pantaluna/312627ee61742850eb679c7d5125e20d – Rolf

+0

@Rolf: Ich denke immer noch, dass es besser ist mit 'co.wrap' (und kann zwei weitere Zeilen speichern). – Bergi

Verwandte Themen