2015-02-23 7 views
16

Ich habe eine Funktion aus einer Bibliothek, die ein Versprechen zurückgibt. Ich muss diese Funktion mehrmals ausführen, aber jede Iteration muss warten, bis die vorherige Aufgabe erledigt ist.Wie synchron lösen Sie eine Kette von es6 Versprechen?

Meine Vermutung war, dass ich dies tun könnte:

promiseReturner(1) 
    .then(promiseReturner(2) 
    .then(promiseReturner(3) 
    .then(...) 

, die unter Verwendung einer Schleife vereinfacht werden könnte:

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    p = p.then(promiseReturner(i)); 
} 
jedoch

, wenn ich das jedes Versprechen in der Kette zu tun bei der ausgeführt wird, gleichzeitig, anstelle von einer nach dem anderen als .then() scheint zu implizieren. Offensichtlich vermisse ich etwas Grundlegendes über Versprechen - aber nachdem ich mehrere Tutorials und Blogposts gelesen habe, bin ich immer noch verloren.

Here's a codepen I wrote up to demonstrate my attempt.

+1

Does 'promiseReturner (n) "ein Versprechen abgeben oder eine Versprechen zurückgebende Funktion machen? – Bergi

Antwort

21

Ihre "Non-Loop" -Lösung sollte auch nicht funktionieren. Sie haben eine Funktion-.then passieren, kein Versprechen:

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    (function(i) { 
     p = p.then(function() { 
      return promiseReturner(i); 
     }); 
    }(i)); 
} 

Wenn diese Funktion ein Versprechen gibt, dann erhalten Sie die Verkettungs Wirkung.

Weitere Informationen über Versprechen auf MDN.


kann mit dem let (Pfeil und Funktionen) vereinfacht werden:

var p = Promise.resolve(); 
for (let i=1; i<=10; i++) { 
    p = p.then(() => promiseReturner(i)); 
} 

Oder .bind (die ES5 ist):

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    p = p.then(promiseReturner.bind(null, i)); 
} 
+2

Vielleicht klarer: "Sie müssen eine Funktion übergeben * ein Versprechen * zurückgeben"? –

+0

egal, dass Sie das später erklären –

+0

Ich hatte versucht, es in eine Funktion früher [siehe hier] (http://codepen.io/anon/pen/zxjExL?editors=001), aber es schien nur die letzte zu laufen versprechen.Warum scheint das Wrapping, das es in einer selbstaufrufenden Funktion blockiert, es zu beheben? –

1

können Sie verwenden async/await es6 Generatoren und eine Bibliothek wie co.

co(function*() { 
    while(upto < 10) { 
    var result = yield Promise.resolve(true); 
    } 
    return result; 
}).then(function (value) { 
    console.log(value); 
}, function (err) { 
    console.error(err.stack); 
}); 

Hier ist ein Detail, wie das funktioniert: http://davidwalsh.name/async-generators

1

Hier ist eine Lösung, die ich verwendet, um das gleiche Problem zu lösen:

var recursiveFunction = function(values) { 
    return new Promise(function(resolve, reject) { 
    if (values.length <= 0) { 
     return resolve(); 
    } else { 
     return promiseReturner(values[0]).then(function() { 
      values.shift(); 
      return recursiveFunction(values).then(function() { 
       resolve(); 
      }); 
     }); 
     } 
    }); 
} 

recursiveFunction([1,2]).then(function(r) { 
console.warn('Finished solving promises sequentially'); 
}) 
0

Wenn Sie es6 verwenden, können Sie erreichen dies mit array.reduce . Ich denke ganz ordentlich.

const functions = [/* array of functions which return promises */]; 
const finalPromise = functions.reduce(async (promise, asyncFn) => { 
    await promise; 
    return asyncFn(); 
}, Promise.resolve()); 
-1

Sie Ihren Code über nsynjs laufen kann, wird es die Ausführung auf jeder Pause-Funktion, die Versprechen zurück, und wartet, bis Versprechen behoben:

var promiseReturner = function(i) { 
 
    return new Promise(function(resolve, reject) { 
 
     setTimeout(function(){ 
 
      resolve("result is "+i) 
 
     }, 1000); 
 
    }); 
 
}; 
 

 
function synchronousCode() { 
 
    for (var i=1; i<=10; i++) { 
 
     var p=promiseReturner(i); // nsynjs will pause here until promise is resolved 
 
     console.log(p.data); // `data` will contain result of the promise 
 
    } 
 
}; 
 
\t 
 
nsynjs.run(synchronousCode, null, function(){ 
 
\t console.log("finish"); 
 
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>

Verwandte Themen