2017-05-24 8 views
2
function getNamesById(nameIds) { 
    var defer = $q.defer(); 

    var result = []; 
    nameIds.forEach(function (nameId) { 
     account.getNameById(nameId).then(function (name) { 
      result[nameId] = name; 
     }); 
    }); 
    defer.resolve(result); 
    return defer.promise; 
} 

Ich habe den obigen Code, der offensichtlich nicht funktioniert wie erwartet. Ich habe ein Array von IDs wiederholen und ein weiteres Array zu konstruieren, um die IDs als Schlüssel haben, und die von einer Asynchron-Funktion genommen WerteRückgabe des Versprechens innerhalb forEach

+0

Sie [kann 'forEach' mit Versprechen nicht verwenden (https://stackoverflow.com/q/37576685/1048572). Vermeiden Sie auch die [latent antipattern] (http://stackoverflow.com/q/23803743/1048572?Was-ist-die-Promose-Construction-antipattern-and-how-zum- Vermeiden-)! – Bergi

+0

Danke Jamiec und @Bergi – uromay

+1

@JaromandaX 'forEach' +' push' ist so hässlich, dass ich es nicht berücksichtigen möchte :-) – Bergi

Antwort

2

Sie sollten nur ein weiteres Versprechen Rückkehr von $q.all

function getNamesById(nameIds) { 

    var result = []; 
    nameIds.forEach(function (nameId) { 
     result.push(account.getNameById(nameId)); 
    }); 
    return $q.all(result); 
} 

und anschließend Kette dass an anderer Stelle

getNamesById(someNameIds) 
    .then(...); 

Ein klarer Weg, dies zu schreiben, wird mit .map statt ein Array deklarieren und mit forEach schieben hinein:

function getNamesById(nameIds) { 
    return $q.all(nameIds.map(function (nameId) { 
     return account.getNameById(nameId) 
    })); 
} 

Wenn ES6 mit (und Ihre Methode ignoriert definitiv alle, aber das erste Argument) diese weiter vereinfacht werden kann:

let getNamesById = nameIds => Promise.all(nameIds.map(account.getNameById)); 

So Von Kommentaren vermute ich, dass Sie versuchen, ein assoziatives Array zurück mit als Schlüssel und das Ergebnis des asynchronen Aufrufs als Wert zu erhalten. Es gibt einen weiteren Schritt, den Sie benötigen - Sie müssen Rückkehr ein Wert von Ihrem then, die Sie später

function getNamesById(nameIds) { 
    return $q.all(nameIds.map(function (nameId) { 
     return account.getNameById(nameId) 
        .then(function(name){ 
         return {id:nameId, name:name}; 
        }) 
    })); 
} 

verbrauchen Wenn Sie diese Methode verbrauchen, können Sie einfach reduce das Ergebnis auf Ihre assoziatives Array

getNamesById(["a","b","c"]) 
    .then(function(results){ 
     var values = results.reduce(function(p,n){ 
      p[n.id] = n.name; 
      return p; 
     },{}); 
     // values is your associative array with keys a,b & c 
    }); 

in ES6 Schrieben macht dies viel weniger ausführlich - der Vollständigkeit halber:

function getNamesById(nameIds) { 
    return $q.all(nameIds.map(
       nameId => account.getNameById(nameId) 
        .then(name => ({id:nameId, name:name})) 
    ); 
} 

und

getNamesById(["a","b","c"]) 
    .then(results => { 
     var values = results.reduce((p,n) => { 
      p[n.id] = n.name; 
      return p; 
     },{}); 
     // values is your associative array with keys a,b & c 
    }); 
+0

mit 'nameIds.map (account.getNameById)' kann problematisch sein, wenn Funktion ' account.getNameById' ignoriert nicht nur das erste Argument (Ich wurde einmal ** gestochen **): p (was ist ein P/A rant?) –

+0

@JaromandaX danke. Antwort aktualisiert. Ihr Zusatz zu Ihrem Die Antwort war * sehr * [passiv/aggressiv] (https://en.wikipedia.org/wiki/Passive-aggressive_behavior) und schien auf mich gerichtet zu sein durch das Zitat "scheinbar nur die Antwort zuerst herauszuplatzen ist der akzeptierte Weg in diesen Tagen" Meine Antwort war weit davon entfernt, "herausgeplatzt" zu sein - aber vielleicht fehlten ein paar Details, von denen ich zugeben muss, dass sie an erster Stelle standen. – Jamiec

+0

war nicht so gedacht - so viele angenommene Antworten scheinen eher die schnellsten zu sein als die beste (meiner Meinung nach) - vielleicht ist es meiner Meinung nach ist schuld: p –

Verwandte Themen