2017-09-13 11 views
1

Ich habe Schwierigkeiten zu verstehen, wie man mit Gruppen von Versprechen arbeitet, die zusammen lösen müssen.Mit Gruppen von Versprechen arbeiten

In meiner Situation möchte ich eine Reihe von Versprechen Aufrufe basierend auf einem Array von IDs machen, und sie selektiv zu einem Ausgabe-Array hinzufügen. Wenn diese PHP wären, würde ich so etwas wie:

$output = [] 
foreach($input as $id) { 

    $result1 = functioncall1($id); 
    $result2 = functioncall2($result1); 

    if ($result2 == 'some filter') { 
    $output[] = $result1; 
    } 
} 

Dies kann nicht mit einem asynchronen Aufruf erfolgen, da die Schleife nicht für das Ergebnis nicht warten, um zurückzukehren. Also ich bin mit Versprechungen mit drossel wie folgt aus:

Promise.map(input, function(id) { 
    promisifedFunction1(id) 
     .then(function(result1) { 
      //process result1 some more 

      promisifedFunction2(result1) 
      .then(function(result2) { 
       //process result2 some more 

       if (result2 == 'some filter') { 
        return result1; 
       }); 

      }); 

     }) 
    .then(function(output) {}); 
} 

ich klar hier etwas fehle, weil mein Ausgang immer nur eine Reihe von undefinierten enthält. Aber es ist anscheinend Mapping und erreicht das Finale dann, wenn ich es erwarte und diese undefinierten Arrays werden nur erzeugt, wenn die Filterung ok ist. Das Undefinierte wird erzeugt, auch wenn der Filter nur eine Literal-Zeichenfolge zurückgibt.

Ich bin Clearing fehlt etwas, aber ich habe Mühe, die Lücken zu füllen.

+0

'Promise.all' ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Referenz/Global_Objects/Versprechen/alle –

Antwort

1

Ich nahm an, das würde hier schon eine Antwort auf SO haben, aber anscheinend nicht (oder wenn es ein paar schnelle Suchen nicht gefunden hat).

Sie wollen eine Struktur wie folgt aus:

let filteredResults = Promise.all(arr.map(x => promisifiedFn1(x))) 
    .then(xs => xs.map(result1 => promisifiedFn2(result1))) 
    .then(ys => ys.filter(someFilteringFn)); 

Promise.all kann als Drehen eines Behälters von innen nach außen durchdacht sein: Sie können es eine Reihe von Versprechungen geben (durch Abbilden Ihre Versprechen-Rückkehr-Funktion über eine Reihe von Inputs) und es gibt Ihnen ein Versprechen eines Arrays der Ergebnisse, die Sie dann wie jedes andere Array behandeln.

Also xs ist ein Array der Ergebnisse der ersten Funktion über die Eingänge zugeordnet, sobald alles verrechnet wird. ys ist die zweite. Ich bin nicht sicher, was Bluebird Promise.map tut, aber Sie könnten möglicherweise die ersten beiden Schritte in meinem Code damit kombinieren.

Da Sie jede Eingabe vollständig bearbeiten, bevor Sie entscheiden, ob Sie das Ergebnis behalten möchten oder nicht, gibt es keine Nachteile für die einfache Verarbeitung der Eingaben mit den beiden asynchronen Schritten und die anschließende Filterung des resultierenden Arrays.

1

Stellen Sie sicher, dass Ihre promisified Funktionen in Ordnung sind, sollte dies auch funktionieren:

var elements = ["one", "two", "three"] 
 
var container = document.querySelector('.results') 
 

 
function promisifiedFunc1(arrayElement) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve('input to the next func ' + arrayElement) 
 
    }, 1000) 
 
    }) 
 
} 
 

 
function promisifiedFunc2(inputFromPreviousFunc) { 
 
    return new Promise(function(resolve, reject) { 
 
    container.innerHTML += "<br>" + inputFromPreviousFunc 
 
    setTimeout(function() { 
 
     resolve('some filter') 
 
    }, 1000) 
 
    }) 
 

 
} 
 

 
Promise.map(elements, function(one) { 
 
    return promisifiedFunc1(one).then(promisifiedFunc2); 
 
    }) 
 
    .filter(function(res2) { 
 
    return res2 === 'some filter'; 
 
    }) 
 
    .then(function(allResults) { 
 
    console.log(allResults); 
 
    container.innerHTML += "<br>All Done!"; 
 
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.0/bluebird.min.js"></script> 
 
<div class="results"></div>

Promise.map können Sie jede Array in ein Array von Versprechen zur Karte und ein neues Versprechen zu erzeugen, das wird wenn alle diese Versprechen gelöst sind. Innerhalb der Mapping-Funktion können Sie die beiden Versprechen verketten.

0

Sie können eta-Reduktion tun, dass Code aussehen zu lassen viel einfacher:

Promise.map(input, promisifedFunction1) 
     .map(promisifiedFunction2) 
     .filter(v => v === 'someFilter') 
     .then(outputFunction); 
Verwandte Themen