2017-06-14 4 views
0

Es gibt viele Antworten für diese Frage, aber die meisten von ihnen synchronisieren die Auflösung der Versprechen (d. H. Das Ende der Ausführung, nicht der Beginn der Ausführung).Laufende Versprechen sequenziell: jedes Versprechen startet, nachdem das vorherige endet

This solution übernimmt wir bereits eine Reihe von Funktionen:

var funcs = [foo, bar, baz, qux]; 

Wie solche Anordnung ohne die Ausführung der Funktionen erstellt wird? Ich habe dies versucht:

var promises = []; 
for (i = 0 ; i < 3, ++i){ 
    promises.push(someFunction(i)) 
} 

function someFunction(i) { 
    return new Promise((resolve, reject) => { 
     console.log(i); 
     resolve(i); 
    }); 
} 

Bis Ende für Schleife das Versprechen Array gefüllt wird, aber someFunction bereits ausgeführt 4 mal. Mit Promise.all oder Q Sequenzen nur Sequenzen verrechnet.

Wie kann ich die wahre Synchronisation des Anfangs dieser Funktionen erreichen? Insbesondere:

foo().then(bar).then(baz).then(qux); 
+0

prüfen diese Antwort: https://stackoverflow.com/a/44371402/7636961 – wostex

+0

ich das in Versprechen API gebaut glaube nicht, dass über diese Funktion verfügt. Sie könnten versuchen, Promise.reduce von Bluebird: http://bluebirdjs.com/docs/api/promise.reduce.html –

+0

@KarelG: genau meine Frage! Wie kann ich es in ein Array schieben, ohne es anzurufen? Ich möchte diese Versprechen in einer For-Schleife on the fly erstellen. – Ari

Antwort

0

Sie müssen nur den Namen der Funktion übergeben, ohne Parameter zu übergeben. In Ihrem Beispiel rufen Sie

 someFunction(i) 

- Sie können die Parameter übergeben i, so ist dies ein Funktionsaufruf. Sie sollten die Funktionen nur nach ihrem Namen drücken. Der Parameter für jede Funktion ist der Wert, der im vorherigen Versprechen aufgelöst wurde.

function someFunction(i) { 
    return new Promise((resolve, reject) => { 
     console.log(i); 
     resolve(i+1); // increase the value here 
    }); 
} 

Auf diese Weise wird der Parameter auf die nächste Funktion um 1 erhöht geben wird aber für die erste Funktion in der Kette sollten Sie die Parameter übergeben. So etwas wie

someFunction(0).then(someFunction).then(someFunction) 

(In dieser Lösung Sie nicht das Array benötigen.)

+0

Wie kann ich diese Funktionen später in einer Sequenz richtig aufrufen? – Ari

+0

@Ari Sie möchten, dass die gleiche Funktion dreimal ausgeführt wird? – Cz01

+0

Ja, mit anderen Parametern. – Ari

1

Das Problem ist

promises.push(someFunction(i)) 

, wenn Sie die promises Array sind bevölkern, die someFunction ist sein wird jedes Mal aufgerufen, bevor der Wert an die Methode .push übergeben wird. So führt es früher als Sie wollen.

Eine Arbeit ist es nicht zu nennen. Das ist nicht einfach zu implementieren, also dachte ich an einen kleinen (aber hässlichen) Hack. Ich habe ein Objekt {p: ..., val: ...} eingeführt, das eine Versprechensfunktion und Werte für diese Zusagefunktion enthält. Wenn Sie mehrere Werte bereitstellen möchten, übergeben Sie einfach ein Array. Die apply() Methode wird es in Ihre Funktionsargumente konvertieren. Die Funktion callPromise übernimmt die korrekte Ausführung der Funktion.

Es kann sein, dass jemand eine bessere Lösung hat, aber das ist eine, an die ich schnell denken kann.

Hier unten ist ein Beispiel, wo die Versprechen nacheinander aufgerufen werden. Ich habe eine zusätzliche Funktion (falls eine andere Funktion mehr als ein Argument hat) als PoC hinzugefügt.

var promises = []; 
 
for (let i = 0 ; i < 3; ++i){ 
 
    promises.push({p: someFunction, val: i}); 
 
} 
 

 
promises.push({p: anotherFunction, val: [100,33]}); 
 
promises.push({p: someFunction, val: 4}); 
 

 
function someFunction(i) { 
 
    return new Promise((resolve, reject) => { 
 
     console.log('someFunction, i: ' + i); 
 
     resolve(i); 
 
    }); 
 
} 
 

 
function anotherFunction(i1, i2) { 
 
    return new Promise((resolve, reject) => { 
 
     console.log('anotherFunction, i1: ' + i1 + ', i2: ' + i2); 
 
     resolve(i); 
 
    }); 
 
} 
 

 

 
function callPromise(prom) { 
 
    if(Object.prototype.toString.call(prom.val) !== '[object Array]') prom.val = [prom.val]; 
 
    return prom.p.apply(null, prom.val); 
 
} 
 

 
console.log('before loop'); 
 
let result = callPromise(promises[0]); 
 
for (let i = 1 ; i < promises.length; ++i) { 
 
    result = result.then(callPromise(promises[i])); 
 
}

+0

Können Sie bitte erklären, was genau CallPromise tut? – Ari

+0

@Ari 'prom' ist das' {p: ..., val: ...} 'Objekt. Es prüft zuerst, ob val ein Array ist. Wenn nicht, mach es zu einem Array. Dann wird die Funktion 'p' mit dem Array val ausgeführt, indem' .apply' verwendet wird. Wenn Sie das Dokument überprüfen, werden Sie feststellen, dass das Array als Argument für die Funktion p zur Verfügung gestellt wird. Diese Funktion kehrt mit einem Versprechen zurück, das dann wie ein Versprechen behandelt werden kann: mit '.then' und' .catch' ect ... – KarelG

Verwandte Themen