2015-02-26 3 views
8

Ich habe dieses Versprechen, dass ein neues Item Dokument erstellt, wenn es nicht in der DB gefunden wird, und speichert sie dann in einem zuvor Collection Dokument erstellt ..Bluebird Promise serielle Iteration und zu modifiziertem Array auflösen?

The Collection Dokument der erste String in einem Array ist, und jeder nachfolgende Der Index im Array wird in eine oder mehrere Dokumentdateien übersetzt.

Promise.each "Resolves to the original array unmodified" und so die letzte return im Promise.each wird die Objekte machen, aber die nachfolgende .then erzeugt das ursprüngliche Array ..

Hier ist das Versprechen (abgekürzt für Lesbarkeit):

globalVar = true; 
collectionId = ""; 
var itemSeries = Promise.each(items, function(element) { 
    if (globalVar == true) { 
     return Models.Collection.findOneAsync({ 
      "name": element 
     }) 
     .then(function(collection) { 
      // promise chain similar to the following else.. 
      // set the collectionId var to an _id 
     }); 
    } else { 
     return Models.Items.findOneAsync({ 
      "name": element 
     }) 
     .then(function(item) { 
      if (item == null) { 
       return Models.Labels.findOneAsync({ 
        "title": element 
       }) 
       .then(function(label) { 
        var newItem = new Models.Items({ 
         name: element, 
         label: label._id 
        }); 
        return newItem.saveAsync(); 
       }).then(function() { 
        return Models.Items.findOneAsync({ 
         "name": element 
        }); 
       }).then(function(item) { 
        item.collection = collectionId; 
        return item.saveAsync(); 
       }).then(function() { 
        return Models.Items.findOneAsync({ 
         "name": element 
        }); 
       }).then(function(item) { 
        allItems.push(item); 
        console.log("allItems: [ "); 
        console.log(allItems); 
        return allItems; 
       }); 
      } 
     }); 
    } 
}).then(function(allItems) { 
    console.log("allItems: [ "); 
    console.log(allItems); 
    return allItems; 
}); 

Und hier ist der letzte der console.log im Promise.each:

allItems: [ 
[ { _id: 54eec5f2b9fb280000286d52, 
    name: 'one', 
    label: 54eec5f2b9fb280000286d51, 
    collection: 54eec5f2b9fb280000286d50, 
    __v: 0 }, 
    { _id: 54eec5f2b9fb280000286d54, 
    name: 'two', 
    label: 54eec5f2b9fb280000286d53, 
    collection: 54eec5f2b9fb280000286d50, 
    __v: 0 } ] 

Und dann nach der anschließenden .then(function(allItems) { hier ist das letzte console.log:

allItems: [ 
[ 'collectionName', 'one', 'two' ] 

Auch später die Variable itemSeries dass = Promise.eachundefined in einem Promise.join macht?

Antwort

20

Die .each Funktion den Wert nicht ändern, die durch die Kette geführt wird:

ich Ihren Code vereinfacht, als Eingabe Ich gehe davon aus:

var items = ['one','two']; 

Für Ihr Code:

Promise.each(items, function(element) { 
    return element+'.'; 
    //return Promise.resolve(element+'.'); 
}) 
.then(function(allItems) { 
    console.dir(allItems); 
}); 

Das Ergebnis ist immer noch ['one','two'], da dies aufgelöste Werte des Arrayssind. Der zurückgegebene Wert in jedem einzelnen hat keinen Einfluss auf den Inhalt des Werts, der an die verkettete then übergeben wird.

Die .map Funktion auf der anderen Seite wird diese Wirkung hat:

Promise.map(items, function(element) { 
    return element+'.'; 
    //return Promise.resolve(element+'.'); 
}) 
.then(function(allItems) { 
    console.dir(allItems); 
}); 

Hier ist der return Wert Wert wird verwendet, um ein neues Array zu erstellen, die dann die then weitergegeben werden. Hier wäre das Ergebnis ['one.','two.'].

Die zwei allItems, die in Ihrem Code erscheinen, sind verschiedene Objekte.

EDIT Für seriell Iteration mit Mapping würde ich eine Hilfsfunktion wie folgt schreiben:

function mapSeries(things, fn) { 
    var results = []; 
    return Promise.each(things, function(value, index, length) { 
     var ret = fn(value, index, length); 
     results.push(ret); 
     return ret; 
    }).thenReturn(results).all(); 
} 

Quelle: Implement Promise.series

+0

Alles klar, wie kann der 'allItems'-Wert zurückgegeben werden? .each ist notwendig, weil die Reihenfolge erforderlich ist. – Stacks

+0

@Maji hat einen Kommentar zu meinem Kommentar hinzugefügt. –

+0

fwiw .Each funktioniert wie .mapSeries in 3.0 seit der Rückgabe der vorhandenen Array hasnt war nützlich – Esailija