2016-07-24 9 views
0

Ich möchte die Tags Format ändern, die ich aus einer der Sammlungen abholen. Stichworte Daten enthalten einig KC ids in einer Anordnung, die ich KC Daten und stecken in TagUnit zu bekommen endgültiges Antwort-Format zu bekommen verwenden.Knoten For-Loop-Rückruf erforderlich

var newTags = Tags.map(function(TagUnit) { 
    for (var i = 0; i < TagUnit.kcs.length; i++) { 
     KCArray = []; 
     KC.findById(TagUnit.kcs[i], function(error, data) { 
      KCMap = {}; 
      KCMap['kc_id'] = data._id; 
      KCMap['kc_title'] = data.title; 
      KCArray.push(KCMap); 
      if (KCArray.length == TagUnit.kcs.length) { 
       TagUnit.kcs = KCArray; 
      } 
     }); 
    } 
    return TagUnit; 
}); 

response.send(JSON.stringify(newTags)); 

Aber ich bekomme nicht das gewünschte Ergebnis. Antwort gibt Tag Daten in initial für statt formatierter Form aus. Ich denke, es ist aufgrund der Ereignisschleife. Ich wäre dankbar, wenn mir jemand dabei helfen könnte.

** Bearbeiten: ** Ich verwende MongoDB als Datenbank und Mungo als ORM.

+1

Haben Sie in [Versprechen] (http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=de) geschaut? Du hast recht, dass dein Problem auf die Event-Schleife zurückzuführen ist. 'newTags' wird am wahrscheinlichsten nicht beim Aufruf von 'response.send' berechnet. – markusthoemmes

Antwort

1

Ich würde vorschlagen, Versprechen zu verwenden, um Ihre asynchronen Operationen zu verwalten, die jetzt der Standard in ES6 ist. Sie sagen nicht, welche Datenbank Sie verwenden (möglicherweise verfügt sie bereits über eine auf Versprechen basierende Benutzeroberfläche). Wenn dies nicht der Fall, dann manuell wir KC.findById() promisify:

function findById(key) { 
    return new Promise(function(resolve, reject) { 
     KC.findById(key, function(err, data) { 
      if (err) return reject(err); 
      resolve(data); 
     }); 
    }); 
} 

Dann, vorausgesetzt, Sie tun können, all diese Vorgänge parallel zu finden, können Sie Promise.all() verwenden beide im Auge zu behalten, wenn sie alle fertig sind, und sie zu bestellen für dich.

var allPromises = Tags.map(function(TagUnit) { 
    var promises = TagUnit.kcs.map(function(key) { 
     return findById(key).then(function(data) { 
      // make resolved value be this object 
      return {kc_id: data._id, kc_title: data.title}; 
     }); 
    }); 
    // this returns a promise that resolves with an array of the kc_id and kc_title objects 
    return Promise.all(promises).then(function(results) { 
     return { 
      _id: TagUnit._id, 
      kcs: results 
     }; 
    }); 
}); 

// now see when they are all done 
Promise.all(allPromises).then(function(results) { 
    response.send(JSON.stringify(results)); 
}).catch(function(err) { 
    // send error response here 
}); 
+0

Ich versuche die Lösung zu testen. In der Zwischenzeit, nur zur Information, ist meine Datenbank mongoDB und ORM ist mongoose. – Rusty

+0

@Rusty - Es war ein bisschen schwer für mich zu sagen, welche Art von Endergebnis Sie wollten. Dieser Code gibt Ihnen eine Reihe von Arrays von Objekten, wobei jedes Objekt 'kc_id' und' kc_title' enthält, weil ich dachte, dass Ihr ursprünglicher Code dies erzeugen wollte. – jfriend00

+0

Ich möchte die ** Antwort ** im folgenden Format gehen. '{" tag_id ":" nienemk29290hu38 "," kcs ": {" kc_id ":" nmdkwmwmwjm4944 "," kc_title ":" ABC "}'. Ihre Lösung scheint fast so zu sein, dass es mir etwas schwer fällt, endgültige Formatierungen durchzuführen. – Rusty

1

Sie verspricht verwenden können oder Async Modul

var async = require('async'); 
... 
function getKC (kc, callback) { 
    KC.findById(kc, function(err, data) { 
     if (err) 
      return callback(err); 

     callback(null, {kc_id: data._id, kc_title: data.title}) 
    }); 
} 

function getKCs (tag, callback) { 
    async.map(tag.kcs, getKC, callback); 
} 

async.map(Tags, getKCs, function(err, results){ 
    if (err) 
     return console.log(err.message); 

    res.json(results); // or modify and send 
}); 

P. S. Vielleicht enthält der Code Fehler. Ich kann es nicht testen.